記在 Hyperf 中多庫連線操作事務注意事項

邢闖洋發表於2020-07-24

業務場景中很多時候我們不止有一個資料庫例項,這時候就需要配置多庫連線。
當我們時候 Hyperf 來作為專案框架時,多庫連線操作事務需要注意 database.php 中配置的每一個連線都是相互隔離的。

如果我們的 database.php 配置檔案如下

return [
    'default' => [
        'database' => 'mysql1',
        ....忽略其他引數
    ],
    'mysql1'=>[
        'database' => 'mysql1',
        ....忽略其他引數
    ],
    'mysql2'=>[
        'database' => 'mysql2',
        ....忽略其他引數
    ],
];

可以看到預設庫為 mysql1。
現在我們來建立三張表

class Test1 extends Model
{
    protected $table = 'test1';

    protected $connection = 'mysql1';
}

class Test2 extends Model
{
    protected $table = 'test2';

    protected $connection = 'mysql1';
}

class Test3 extends Model
{
    protected $table = 'test3';

    protected $connection = 'mysql2';
}

這時候如果是按照 Laravel 的習慣,我們在操作事務時只要是不跨例項的庫,都無需指定資料庫連線

//如果跨例項,則需要指定資料庫連線
//Db::connection("mysql1")->beginTransaction();
//Db::connection("mysql2")->beginTransaction();
Db::beginTransaction();
try {

    //mysql1資料庫
    DB::table("test1")->insert([
        'code' => 1,
    ]);

    //mysql2資料庫
    DB::table("test3")->insert([
        'name' => 1
    ]);

    Db::commit();

} catch(\Throwable $e) {

    Db::rollback();
    $this->error("失敗了=".$e->getMessage());
}

在 Hyperf 中需要注意,上面我們說到的每個連線都是相互隔離的,所以我們在操作事務的時候如果模型中 connection 指定的不是 default,則在操作事務時候需要指定連結

Db::connection('mysql1')->beginTransaction();
try {

    Db::table("test1")->insert([
        'name' => 1,
    ]);

    Db::table("test2")->insert([
        'name' => 2 
    ]);

    Db::connection('mysql1')->commit();

} catch (\Throwable $e) {
    Db::connection('mysql1')->rollback();
}

否則就會導致事務失效的情況

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章