前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL里trx_mysql_thread_id为0 的事务导致大量锁等待超时该咋整

MySQL里trx_mysql_thread_id为0 的事务导致大量锁等待超时该咋整

作者头像
July
修改2019-08-10 18:35:26
2.4K0
修改2019-08-10 18:35:26
举报
文章被收录于专栏:数据库干货铺数据库干货铺

今天巡检时突然发现有很多锁等待超时的情况,原以为是一个简单的小事,一查,结果令人深思。

1. 问题现象

发现日志中出现了大量的 ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 错误

2. 排查过程

发现此类情况后,挑了其中一个SQL脚本手动运行了一下,发现同样报此错误

代码语言:javascript
复制
mysql> UPDATE tbname SET column_name = 2 WHERE col_id= '25945fa285904ea59cd92a73a3850ceb' AND aYear = 2018 AND aMonth = 5;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
出现此情况,第一反应是查看是否有未提交的事务或有其他的SQL运行时也需要对该条记录进行写操作。
代码语言:javascript
复制
# 查看正在运行的sqlselect  *  from information_schema.processlist where info is not null;结果集中并无对该表的任何操作,因此,很大可能是有未提交的事务了。 # 查看事务SELECT  *FROM  information_schema.INNODB_TRX;

  结果中确实存在大量事务,此时原本以为已经查到问题,直接将对应为提交的事务杀掉即可(已与相关人员确认可以杀)

于是把脚本准备好,准备大开杀戒

代码语言:javascript
复制
#  杀sql会话SELECT  concat('kill ',trx_mysql_thread_id,";")t_sql FROM  information_schema.INNODB_TRX;但是仔细一看,trx_mysql_thread_id全部都是0 

经确认,trx_mysql_thread_id=0 的事务全部为XA事务。

3. 处理过程

因为trx_mysql_thread_id=0 的事务无法通过kill trx_mysql_thread_id 的方式处理,所以,需要回滚这些XA事务。

查看XA事务信息

代码语言:javascript
复制
mysql>  xa recover;+------------+--------------+--------------+-------------------------------+| formatID   | gtrid_length | bqual_length | data                          |+------------+--------------+--------------+-------------------------------+| 1096044365 |           20 |            9 | tm156393736565426841tm1333009 || 1096044365 |           20 |            9 | tm156393708714926372tm1332251 || 1096044365 |           20 |            9 | tm156393726166726646tm1332693 |...+------------+--------------+--------------+-------------------------------+43 rows in set (0.00 sec)

拼接生成XA事务回滚脚本

代码语言:javascript
复制
# XA事务回滚命令的格式:xa rollback 'left(data,gtrid_length)','substr(data,gtrid_length+1,bqual_length)', formatID;
# 以上查出来的信息拼接结果为(以下举其中一个为例)xa rollback 'tm156393736565426841','tm1333009',1096044365;执行回滚脚本
代码语言:javascript
复制
mysql> xa rollback 'tm156393736565426841','tm1333009', 1096044365;Query OK, 0 rows affected (0.00 sec)

检查是否还存在未提交的XA事务

发现已经无正在执行事务

XA信息

测试能否正常更新记录

# 发现也已正常

再检查各日志,此类锁等待问题也未出现。

4. XA事务(分布式事务)浅析

在本应用中,为了降低单点压力,根据业务情况进行了分表分库,将表分布在不同的库中(库分布在不同的机器上)。在这种场景下,事务的提交会变得相对复杂,因为多个节点(库)的存在,可能存在部分节点提交失败的情况,即事务的ACID特性需要在各个不同的数据库实例中保证。比如更新db1库的A表时,必须同步更新db2库的B表,两个更新形成一个事务,要么都成功,要么都失败,起初,为了简化应用程序在事务处理的难度,因此直接使用MySQL数据库的分布式事务。

两阶段提交

分布式事务通常采用2PC协议,全称Two Phase Commitment Protocol。该协议主要为了解决在分布式数据库场景下,所有节点间数据一致性的问题。分布式事务通过2PC协议将提交分成两个阶段:prepare, commit/rollback。

阶段一为准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向transaction manager报告已准备就绪。 阶段二为提交阶段(commit)。当transaction manager确认所有参与者都ready后,向所有参与者发送commit命令。

如下图所示:

因为XA 事务是基于两阶段提交协议的,所以需要有一个事务协调者(transaction manager)来保证所有的事务参与者都完成了准备工作(第一阶段)。如果事务协调者(transaction manager)收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。MySQL 在这个XA事务中扮演的是参与者的角色,而不是事务协调者(transaction manager)。

MySQL XA 事务示例

代码语言:javascript
复制
mysql> XA START 'xatest';Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO mytable (i) VALUES(10);Query OK, 1 row affected (0.04 sec)
mysql> XA END 'xatest';Query OK, 0 rows affected (0.00 sec)
mysql> XA PREPARE 'xatest';Query OK, 0 rows affected (0.00 sec)
mysql> XA COMMIT 'xatest';Query OK, 0 rows affected (0.00 sec)

XA事务的性能问题

XA的性能很低。一个数据库的事务和多个数据库间的XA事务性能对比可发现,性能差10倍左右。因此要尽量避免XA事务,例如可以将数据写入本地,用高性能的消息系统分发数据。或使用数据库复制等技术。只有在这些都无法实现,且性能不是瓶颈时才应该使用XA。并发高的情况下不建议使用,可以借助redis或其他方法来改造。

关于XA事务的问题及优化的方案有什么建议可以留言沟通。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库干货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档