tp5或tp5.1中启用了事务,但没有正确回滚

tp5或tp5.1中的自动事务没有正确回滚问题

在tp5或tp5.1中的事务,无论自动事务还是手动事务,只有sql执行报错了才会中断执行并回滚,但如果sql没报错,只是影响行数为0(什么都没插入或更新),事务最后是会被提交的!

这个在用tp5或5.1的事务的时候务必注意,不然就会出现用了事务,但依然把错误数据写入的情况。

解决方案:

//首先,全部事务都改用手动事务,不要用自动事务
// 启动事务
Db::startTrans();
try{
	//然后在每段sql后都判断返回结果是否为true,如果不为true就马上抛出错误,如(以tp5为例):
	$xxx = new XxxModel();
	$res= $xxx->insert($data);
	if(!$res && $xxx->getChangedData()){
		return json(['code'=>-1,'msg'=>'sql执行失败了!']))
	}
    
    // 提交事务
    Db::commit();    
} catch (\Exception $e) {
    // 回滚事务
    Db::rollback();
}

2020-04-11更新:
可能会有同学对这种场景比较少遇到,而我也从今天的评论中发现我的确没有详细说明具体场景,所以这里更一下,说下我当时是具体什么场景下遇到这种情况的:
首先明确:当时的引擎是inndb,并不是myisam,是支持事务的。
场景:假设事务的try catch中有两条sql语句而且两条sql语句都是正确的sql语句,但我希望A语句如果没有写入任何东西,B语句也不要执行。如果对thinkphp的执行结果进行判断,A语句可能会因为数据的确没有任何变动或者其他原因的确没有任何写入或更新操作,而B语句依然正常执行了。对thinkphp来说,数据因为没有变动所以影响行数为0并不是错误,只要sql语句能正常执行无论影响行数是否为0,都不算错误,都不会回滚。

这个笔记是我很久之前写下的,也是刚接触thinkphp时遇到的,老实说也很少遇到上述的场景,只是的确发生过这种情况。后来经过看thinkphp的源码,模型类中其实是有getChangedData()方法(这个方法在手册中并未提及,全文搜索也搜不出来)能判断到底有没数据变动,所以上面的示例代码中的if判断中也增加了getChangedData()的判断。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值