mysql事务未提交 也未回滚

  • Post author:
  • Post category:mysql


公司的一哥们在使用事务时未进行commit,链接断开后数据库执行了回滚操作,导致线上直播相关库的部分数据丢失,本文通过mysql命令行模拟该事故,并提供解决该问题的思路。希望对大家有帮助。



一、场景模拟

通过命令行模拟两个数据库链接,同时开启事务,操作同一行数据。

在数据库链接1开启事务之后,执行rollback之前,数据库链接2开启事务并执行更新操作。

  • 原始数据
id name pinyin description
22193 跽棺反侧 ji’guan’fan’ce !!!形容人多拥挤~~~111
  • 数据库链接1

数据库连接1

  • 数据库链接2

    数据库链接2

实际执行中,数据库链接2在执行update操作时会卡住,排队等待数据库链接1释放操作完成。

在数据库链接1执行rollback操作后,数据库连接2执行commit操作,此时查看数据,会发现数据库中的数据并未更新成功,即数据库链接2的数据丢失。



二、紧急处理

如果线上碰到该问题,首先把出问题的线程kill掉,防止影响更多的正常功能,然后再根据mysql的binlog对受影响的数据进行恢复。

具体使用到的命令在第四部分。



三、原因分析

  • 事务过程中执行其他非数据库操作,导致事务长期未被处理。
  • 事务处理异常或实现逻辑有误,导致事务未被正常处理。
  • 网络,数据库负荷过大等。



四、相关命令



1、查看正在执行的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

在这里插入图片描述

上图可以查看到正在进行的事务(未进行commit)操作的线程信息,线程id为122985;



2、查看正在锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;



3、查看等待锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;



4、查看所有的线程列表

show full processlist;

在这里插入图片描述

结合第一步查到的线程id,可以确定该事务涉及到的表名和数据库链接信息。


确认出现问题的sql在该线程id时,及时使用下面语句kill掉线程,防止影响更多的数据。

kill 122985;



5、定位未提交的事务执行的sql语句

通过以上步骤并不能直观的定位到出问题的sql语句,此时我们可以通过开启通用日志的方式,定位具体的sql语句。

# 查看general log配置
show variables like '%general_log%'

# 开启general log
SET GLOBAL general_log = 1;

通用日志会记录所有sql信息,数据量很大,建议只在排查错误时开启,线上关闭。

此时根据找到

进程号



时间戳

找到对应的记录,定位具体的sql。

参考链接:


https://blog.csdn.net/flysnownet/article/details/114837550



https://www.cnblogs.com/kerrycode/p/11013479.html



https://blog.csdn.net/emoers/article/details/77971468



https://cloud.tencent.com/developer/article/1511089



版权声明:本文为Martin_chen2原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。