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('[email protected]'); $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('[email protected]'); $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)); }
这样就完美解决。