在tp5或者tp5.1的事务中踩了不少坑,所以在这里分享一下自己趟过的坑。
tp事务中遇到过不少的情况导致事务没有正确回滚的。
-
tp5及tp5.1如果没有任何数据更新是不会报错的,这个坑可以详细参考我之前的一篇博客文章: tp5或tp5.1中启用了事务,但没有正确回滚
-
基于mysql的事务特性:事务必须是在同一个数据库连接中才能生效。tp5.*中的事务也必须在同一个数据库连接当中。
但是!重点来了,如果在tp5.*的模型属性中配置了$connection
属性(这个属性的用途大家可以自行到开发手册上查)就会导致每次实例化不同模型的时候,就会创建不同的数据库连接,导致事务并未在同一个数据库连接中执行,自然就会导致事务无法正确回滚。
举个栗子:
//假设模型A、模型B都配置了$connection属性
$modelA = new A();
$modelB = new B();
Db::startTrans();
try{
$modelA->save(['aaa'=>123])
$modelB->save(['bbb'=>321])
Db::commit();
}catch (\Exception $e){
Db::rollback();
}
//上面的事务如果出错了是无法正确回滚的,因为$modelA和$modelB不在同一个事务当中。
解决方案1:不配置$connection
属性
解决方案2:如果一定要配置$connection
属性(一般用于多数据库的情况下)
要一个个模型的开启、回滚事务:
//假设模型A、模型B都配置了$connection属性
$modelA = new A();
$modelB = new B();
$modelA::startTrans();
$modelB::startTrans();
try{
$modelA->save(['aaa'=>123])
$modelB->save(['bbb'=>321])
$modelA::commit();
$modelB::commit();
}catch (\Exception $e){
$modelA::rollback();
$modelB::rollback();
}