目录
自测过程中,修改指定的一条数据报错
SQL: update XXX set status_id = ?, about_id = ? where id in ( 109 );
报错详情
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve com.XXXMapper.updateXXX()
### The error occurred while setting parameters
### SQL: update XXX set status_id = ?, about_id = ? where id in ( ? )
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
该条数据被锁定的可能原因
1、其他sql也在修改该条数据
查看正在运行的sql:select * from information_schema.processlist where info is not null;
可见没有对该条数据修改的操作
2、未提交的事务里对该条数据进行了修改
查看事务:SELECT * FROM information_schema.INNODB_TRX;
可以将未提交的事务kill掉:SELECT concat('kill ', trx_mysql_thread_id, ";") t_sql FROM information_schema.INNODB_TRX;
但是可见,未提交的事务为XA事务,trx_mysql_thread_id=0 的事务全部为XA事务。
解决:回滚XA事务
查询XA事务信息:xa recover;
回滚XA事务
XA事务回滚命令的格式如下(使用的字段如上事务信息组装执行即可)
# 回滚XA事务格式
xa rollback 'left(data,gtrid_length)', 'substr(data,gtrid_length+1,bqual_length)', formatID;
# 本例处理
xa rollback '10.220.17.74.tm163972871540800001', '10.220.17.74.tm3', 1096044365;
回滚后发现更新正常了,问题解决
XA事务
XA(eXtended Architecture)是指由 X/Open 组织提出的分布式交易处理的规范。XA 是一个分布式事务协议,由 Tuxedo 提出,所以分布式事务也称为XA 事务。
概述
XA 协议主要定义了事务管理器TM和资源管理器RM之间的接口
事务管理器TM(Transaction Manager,协调者):协调参与全局事务中的各个事务。需要和参与全局事务的所有资源管理器进行通信,负责各个本地资源的提交和回滚。
资源管理器RM(Resource Manager,参与者):提供访问事务资源的方法,通常一个数据库就是一个资源管理器,如Oracle、DB2、MySQL,这些商业数据库都实现了XA 接口
分布式事务实现
XA 事务是基于两阶段提交(Two-phaseCommit,2PC)协议实现的,可以保证数据的强一致性。
阶段一为准备阶段prepare,即所有的参与者准备执行事务并锁住需要的资源。当参与者Ready时,向TM 汇报自己已经准备好。
阶段二为提交阶段commit。当TM 确认所有参与者都Ready 后,向所有参与者发送COMMIT 命令。
出现锁超时的根本原因
如果执行分布式事务的mysql crash了,MySQL按照如下逻辑进行恢复:
a. 如果这个xa事务commit了,那么什么也不用做。
b. 如果这个xa事务还没有prepare,那么直接回滚它。
c. 如果这个xa事务prepare了,还没commit,那么把它恢复到prepare的状态,由用户去决定commit 或 rollback。
当mysql crash后重新启动之后,执行“XA RECOVER;”查看当前处于 prepare 状态的XA事务,然后 commit 或 rollback 它们。
总结,所以是在事务 prepare后commit前,发生mysql crash了,该情况是要由用户决定该 commit 还是 rollback,所以此时是prepare状态,而准备状态是所有的参与者准备执行事务并锁住需要的资源,资源已经被锁住了,所以再去请求时,发生了锁超时。