如题:我们在写一个模块的时候同一个方法里对数据库进行了两次更新操作,同时都使用了事务来操作。
原来的代码是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// 更新事务1 $data = [ 'day_num'=>0, ]; DB::beginTransaction(); try{ $userInfoModel::where('id','!=',0)->update($data); DB::commit(); }catch (\Exception $e){ DB::rollBack(); } //更新事务2 $data = [ 'pid_day_num'=>0, ]; DB::beginTransaction(); try{ $userInfoModel::where('pid','!=',0)->update($data); DB::commit(); }catch (\Exception $e){ DB::rollBack(); } |
遇到的问题是偶发性执行不成功,各种排查后,单独测试语句都能执行成功,最后发现是两个事务放到一起处理时,如果某一个不能成功会导致另外一个也不成功。由于我们的这个方法是在php-cli模式下执行的,让排查更难了。
最后发现了Laravel的事务机制是根据同一个方法来判断的,同时执行这个方法时其他事务的不成功也会影响其他的事务。当然这里的事务嵌套也是有问题,正确的事务嵌套应该是这样的:
1 2 3 4 5 6 7 8 |
$data = [ 'day_num'=>0]; DB::beginTransaction(); try{ $userInfoModel::where('id','!=',0)->update($data); }catch (\Exception $e){ DB::rollBack(); } DB::commit(); |
总结就是,当我们需要同时使用多个事务同时执行时,请注意事务的嵌套。如果单个事务失败会导致当前所有的事务提交失败,导致后续事务无法提交,导致mysql中的数据更新失败。