XA 协议引出的问题
如果不懂 XA 协议,直接看下面的文章把:
https://dtm.pub/practice/xa.html
下面是我这篇文章主要想说的:(以下是我测试得出的,可能有误)
问题:如果 commit 阶段前一个分事务 commit 成功(无法回滚),而 另一个分事务在要 commit 时宕机了,此时该怎么办?
先说答案:只要是 prepare 成功,即表示该事务已经执行且 redo 日志已经刷新到磁盘。所以我们只需要宕机重启,然后客户端不断进行 commit 尝试,该事务还是能够正常 commit。这就与普通的事务有区别,普通事务在宕机后,会直接回滚。而 prepare 后的 XA 事务则不会。
注意:未 prepare 的 xa 事务,宕机重启会自动回滚,无法继续 prepare 和 commit。
测试
1
2
3
4
5
6
7
|
mysql> select * from grades;
+------------+-----------+-------+
| id | course | grade |
+------------+-----------+-------+
| 2125121024 | 数据库 | 99 |
+------------+-----------+-------+
1 row in set (0.00 sec)
|
- 执行 xa 事务到 prepare 阶段,待 commit
1
2
3
4
5
6
7
8
9
10
11
|
mysql> xa start 'c';
Query OK, 0 rows affected (0.00 sec)
mysql> delete from grades where grade=99;
Query OK, 1 row affected (0.00 sec)
mysql> xa end 'c';
Query OK, 0 rows affected (0.00 sec)
mysql> xa prepare 'c';
Query OK, 0 rows affected (0.01 sec)
|
很明显,由于 xa 事务的原因,该查询超时了
1
2
|
mysql> select * from grades for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
|
- kill 掉 mysql 服务端,模拟宕机场景。然后重启 mysql 服务端。
1
2
3
4
|
ayang@Ubuntu22:~$ ps -aux | grep mysql
mysql 420584 0.0 0.6 1624532 187852 ? Sl 12:14 0:02 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
ayang@Ubuntu22:~$ sudo kill -9 420584
ayang@Ubuntu22:~$ sudo systemctl start mysql
|
可以看到依旧超时了,说明 xa 事务还存在,即使宕机重启了。
1
2
|
mysql> select * from grades for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
|
提交成功,查询立刻返回。说明 prepare,宕机重启后,依旧能够 commit
1
2
3
4
5
|
mysql> xa commit 'c';
Query OK, 0 rows affected (0.00 sec)
mysql> select * from grades for update;
Empty set (0.00 sec)
|
End