0

一次启用事务 begin 没有 commit 的事故

 2 years ago
source link: https://102no.com/2022/03/08/mysql-begin-no-commit/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一次启用事务 begin 没有 commit 的事故

0 条评论

最近在公司接到了一个工单,表象是运营人员在配置一个表单的时候执行一个接口请求,所有的日志和返回都是正确,但是 updateinsert 语句都没有执行,日志系统却都追踪到执行了此语句。更奇怪的是,这个接口的前半部分都执行成功,后半部分都失败了。如下中语句1、语句2、语句3、都成功了。语句4、语句5、语句6都失败了。

伪代码如下:

$parameters = [];
$db->select;//语句1
$db->insert;//语句2
$db->update;//语句3
$db->begin;
$re = $this->judge(parameters)
if($re == false){
return false;
$db->commit;
$db->update;//语句5
$db->insert;//语句6
return true;
function judge(parameters){
if ( $parameters[xx] = null){
$db->update;//语句4
return true;

拿到这个问题按照经验来讲,就是通过几个方面来排查:

  1. 代码问题,是否有bug
  2. 是否启用了事务,执行失败导致回滚。
  3. 是否是因为数据库配置了主从,updateinsert 的主表,select 的从表,但是主从不一致。

随后和架构师以及运维沟通,排除了3,数据库日志都显示正常。那就去排查2,发现虽然代码中有一个事务,但是并不影响主流程的执行。1排查了半天,由于是老代码,且写代码的人离职了,所以并不能仔细的追踪到问题点。

于是就造了一些数据,把线上的拉到本地执行,发现了问题的真正所在:1+2一起造成了这次bug。

在语句3之后开启了事务,参数 $parameters[xx] = null 的时候,加了一个判断,问题是在判断之后,直接返回了个true,也就是说此时开启了事务,随后所有的语句都会掉到这个事务中,由于一直没有commit,语句4和语句4以后的sql都得不到执行。在长时间没有执行的情况下,sql语句会自动回滚。相当于语句4和语句4以后的sql都没有执行。但是只从代码上看,语句5、语句6的确是执行到了。

所以 实际上,本次事故,的原因是有两个:

  • 第一是代码问题。
  • 第二是我们的日志系统没有追中到事务的执行,只是单纯的记录了sql的执行。

直接修复代码即可。使用事务,一定要完整且闭合。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK