Can
Be Better

Laravel 不同数据库的事务回滚失败问题

Laravel的Mysql事务处理可以范例如下

// Open a try/catch block
try {
    // Begin a transaction
    DB::beginTransaction();

    // Do something and save to the db...

    // Commit the transaction
    DB::commit();
} catch (\Exception $e) {
    // An error occured; cancel the transaction...
    DB::rollback();

    // and throw the error again.
    throw $e;
}

很常规,但是需求是使用不同的数据库即需要配置不同的connection。代码如下所示

public function devUserCreateTest()
{
    DB::beginTransaction();

    try {

        $childUser  = new ChildUser; // Exists in database B
        $parentUser = new User; // Exists in database A

        $parentUser->setEmailAttribute('mike@yourmomshouse.com');

        $parentUser->save();

        $childUser->parent_user_id = $parentUser->id;

        $message = sprintf('Parent user id: %s', serialize($childUser->id));

        $childUser->save();

        $message = sprintf('Core user id: %s | hta user id: %s', serialize($parentUser->id), serialize($childUser->id));

        throw new Exception('Testing....');

        DB::commit();

    } catch (Exception $e) {

        Log::warning(sprintf('Exception: %s', $e->getMessage()));

        DB::rollback();
    }

    return $this->buildResponse(array('message' => $message));
}

不出意外的话即使出错了DB::rollback()也不会生效。database.php中的engine也设置为了InnoDB。

很奇怪的问题

但是使用默认的数据库连接比如

DB::beginTransaction();

DB::connection(‘mysql’)->table(‘test’)->insert($datas);

这句话可以被事务影响。但是DB::connection(‘other_connection’)->table(‘test’)->insert($datas);并不受事务的影响。找了好久发现需要每个数据库单独指定事务,代码如下:

app/models/ChildUser.php :

class ChildUser extends Eloquent
{
    protected $connection = 'some_connection'; // as defined in app/config/database.php
}
public function devUserCreateTest()
{
    DB::beginTransaction();
    DB::connection('some_connection')->beginTransaction(); // same as the one used in model ChildUser

    try {

        $childUser  = new ChildUser; // Exists in database B
        $parentUser = new User; // Exists in database A
        $parentUser->setEmailAttribute('mike@example.com');
        $parentUser->save();
        $childUser->parent_user_id = $parentUser->id;
        $message = sprintf('Parent user id: %s', serialize($childUser->id));
        $childUser->save();
        $message = sprintf('Core user id: %s | hta user id: %s', serialize($parentUser->id), serialize($childUser->id));
        throw new Exception('Testing....');
        DB::commit('some-connection');
    } catch (Exception $e) {
        Log::warning(sprintf('Exception: %s', $e->getMessage()));
        DB::connection('some_connection')->rollback();
    }
    return $this->buildResponse(array('message' => $message));
}

这样就完美解决。

未经允许不得转载:最长的路 » Laravel 不同数据库的事务回滚失败问题

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址