今天执行了 seata的XA事务后,因为版本问题,导致无法回滚,这时就要手动清理这些XA事务,不然数据库的正常事务都无法提交的。本地锁没释放。
说明下:xa事务就是数据库层面的实现。 seat-xa的事务只是优化了一下xa的一些问题。具体参数seata的1.4.0版本。比如:不支持重入锁:一个xa全局事务中,再一个分支事务的connection已经做了commit后,他涉及到的数据,是持有本地锁不会释放的。
其中seata-at支持at支持锁重入。
然后出现问题可能xa死锁了,排查下数据库有没有xa事务存在:
直接上图查看XA的事务:
经确认,trx_mysql_thread_id=0 的事务全部为XA事务。
处理过程
因为trx_mysql_thread_id=0 的事务无法通过kill trx_mysql_thread_id 的方式处理,所以,需要回滚这些XA事务。
拼接生成XA事务回滚脚本
# XA事务回滚命令的格式:
xa rollback 'left(data,gtrid_length)','substr(data,gtrid_length+1,bqual_length)', formatID;
# 以上查出来的信息拼接结果为(以下举其中一个为例)
xa rollback '172.xx.xx.xx.xx:8091:50164878136127488','-50164878593306625',9752
执行回滚脚本
Query OK, 0 rows affected (0.00 sec)
检查是否还存在未提交的XA事务
发现已经无正在执行事务
测试能否正常更新记录
以下参考其它作者的XA事务的说明如下:
XA事务(分布式事务)浅析
在本应用中,为了降低单点压力,根据业务情况进行了分表分库,将表分布在不同的库中(库分布在不同的机器上)。在这种场景下,事务的提交会变得相对复杂,因为多个节点(库)的存在,可能存在部分节点提交失败的情况,即事务的ACID特性需要在各个不同的数据库实例中保证。比如更新db1库的A表时,必须同步更新db2库的B表,两个更新形成一个事务,要么都成功,要么都失败,起初,为了简化应用程序在事务处理的难度,因此直接使用MySQL数据库的分布式事务。
两阶段提交
分布式事务通常采用2PC协议,全称Two Phase Commitment Protocol。该协议主要为了解决在分布式数据库场景下,所有节点间数据一致性的问题。分布式事务通过2PC协议将提交分成两个阶段:
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)
阶段一为准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者ready时,向transaction manager报告已准备就绪。
阶段二为提交阶段(commit)。当transaction manager确认所有参与者都ready后,向所有参与者发送commit命令。
如下图所示:
因为XA 事务是基于两阶段提交协议的,所以需要有一个事务协调者(transaction manager)来保证所有的事务参与者都完成了准备工作(第一阶段)。如果事务协调者(transaction manager)收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。MySQL 在这个XA事务中扮演的是参与者的角色,而不是事务协调者(transaction manager)。
XA事务的性能问题
XA的性能很低。一个数据库的事务和多个数据库间的XA事务性能对比可发现,性能差10倍左右。因此要尽量避免XA事务,例如可以将数据写入本地,用高性能的消息系统分发数据。或使用数据库复制等技术。只有在这些都无法实现,且性能不是瓶颈时才应该使用XA。并发高的情况下不建议使用,可以借助redis或其他方法来改造。