最近在公司接到了一个工单,表象是运营人员在配置一个表单的时候执行一个接口请求,所有的日志和返回都是正确,但是 update
和 insert
语句都没有执行,日志系统却都追踪到执行了此语句。更奇怪的是,这个接口的前半部分都执行成功,后半部分都失败了。如下中语句1、语句2、语句3、都成功了。语句4、语句5、语句6都失败了。
伪代码如下:
|
|
拿到这个问题按照经验来讲,就是通过几个方面来排查:
update
和 insert
的主表,select
的从表,但是主从不一致。随后和架构师以及运维沟通,排除了3,数据库日志都显示正常。那就去排查2,发现虽然代码中有一个事务,但是并不影响主流程的执行。1排查了半天,由于是老代码,且写代码的人离职了,所以并不能仔细的追踪到问题点。
于是就造了一些数据,把线上的拉到本地执行,发现了问题的真正所在:1+2一起造成了这次bug。
在语句3之后开启了事务,参数 $parameters[xx] = null
的时候,加了一个判断,问题是在判断之后,直接返回了个true,也就是说此时开启了事务,随后所有的语句都会掉到这个事务中,由于一直没有commit,语句4和语句4以后的sql都得不到执行。在长时间没有执行的情况下,sql语句会自动回滚。相当于语句4和语句4以后的sql都没有执行。但是只从代码上看,语句5、语句6的确是执行到了。
所以 实际上,本次事故,的原因是有两个:
直接修复代码即可。使用事务,一定要完整且闭合。