MySQL 5.7 BUGFIX BUG#12161

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:
在MySQL 5.7版本里,大量遗留很多年的bug都被fix掉了,bug#12161就是其中一个,该bug在2005年第一次report到Bug list上,十年之后终于在MySQL 5.7.7 第一个RC版本被fix了。
Bug描述
当我们显式开启一个XA事务,执行操作,并完成XA PREPARE后,如果Kill session或者主动断开,再重连执行XA RECOVER,之前的这个XA事务是丢失了的。

例如:
mysql> XA BEGIN ‘abc';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 VALUES (1,2,3);
Query OK, 1 row affected (0.00 sec)
mysql> XA END ‘abc';
Query OK, 0 rows affected (0.00 sec)
mysql> XA PREPARE ‘abc';
Query OK, 0 rows affected (0.00 sec)
mysql> Ctrl-C — exit!
Aborted
mysql> XA RECOVER;
Empty set (0.00 sec)
有趣的是,如果在XA PREPARE后把实例KILL掉,是可以通过XA RECOVER恢复的:
mysql> XA RECOVER;
+———-+————–+————–+——+
| formatID | gtrid_length | bqual_length | data |
+———-+————–+————–+——+
| 1 | 3 | 0 | abc |
+———-+————–+————–+——+
1 row in set (0.00 sec)
mysql> XA COMMIT ‘abc';
Query OK, 0 rows affected (0.00 sec)
虽然实例异常重启可以恢复事务,但引入的另外一个问题是:事务变更的binlog丢失,导致主备数据不一致。
bug产生的原因也很简单:在退出session时,线程总是会去无条件的回滚掉自己尚未提交的事务。
官方修复:
a.持久化
为了解决这个问题,将XA的两阶段记录到了Binlog中;
对于上文描述的序列,当执行到XA PREPARE时,记录第一阶段的binlog,如下:
Query event : XA START X’616263′,X’’,1       // 这里的’616262’即是’abc’的十六进制编码
Table_map event
Write_rows event
Query event:XA END X’616263′,X”,1
XA_prepare event: XA PREPARE X’616263′,X’’,1 
这时候该XA事务同时在InnoDB层(事务处于Prepare状态,Redo持久化到磁盘)和Server层都有持久化信息。
其中XA_PREPARE事件是新引入的事件类型(内部类为XA_prepare_event),日后版本升级需要注意到这个低版本不兼容事件。
再执行XA COMMIT ‘abc’,产生新的事件:
Query event:XA COMMIT X’616263′,X”,1
如果执行XA ROLLBACK,则记录:
Query event:XA ROLLBACK X’616263′,X”,1
由于XA PREPARE和XA COMMIT是分开执行的,因此在这两个事件中间可能存在别的事务,备库复制线程需要处理这种情况。
为了实现XA PREPARE写binlog,对binlog_prepare进行了扩展,这里会调用mysql_bin_log.commit, 将cache中的binlog刷到文件中。
Tips:XID可以包含三个部分:gtrid, [, bqual [, format ID]],其中gtrid是必选的,表示全局标示,bqual是分支标识,默认为空’’,format ID是一个unsigned整型,默认值为1,在上例中,我们只指定了gtrid为’abc’,因此bqual段和format ID均为默认值。更具体的描述参考官方文档http://dev.mysql.com/doc/refman/5.7/en/xa-statements.html
b. 如何恢复
当会话断开时(例如kill session或者一次干净的shutdown/restart操作),我们必须要能恢复改事务,传统的逻辑是在cleanup时,直接回滚所有的活跃事务。在新版本中,需要对XA PREPARE的事务做特殊处理(THD::cleanup),如果处于Prepare状态,就将事务的in_recovery设置为TRUE,并更新到hash表transaction_cache中(transaction_cache_detach),该hash表用于维护所有XA事务。
对于非XA的活跃事务,在会话断开时,依然采用回滚策略。
当重连客户端后,我们可以直接执行 XA COMMIT ‘abc’,这时候会通过XID关键字是搜索transaction_cache并将对应的事务提交掉。
同时BINLOG的状态要保持一致,如果XA PREPARE没有记录Binlog, XA COMMIT也不应该记录。
c. 备库复制
由于XA PREPARE和XA COMMIT是分开记录的,当碰到XA COMMIT时,备库采用等待之前的事务全部完成,然后再执行的方式(相当于退化到串行)。
我们知道在一个正常的session过程中,总是为其cache一个事务对象,新的事务会重用这个事务对象,避免多次分配;而XA事务的COMMIT和PREPARE是分离的,需要为XA事务单独分配事务对象。 因此复制线程执行XA START时,将其拥有的事务对象临时保存起来(detach_native_trx),当执行到XA_prepare_log_event事件时,再将其恢复给复制线程,同时XA事务对象关闭read view,将is_recovered设置为TRUE。(函数innodb_replace_trx_in_thd)
随后复制线程在执行到XA COMMIT时直接根据XID进行提交。
参考:
代码: git show f4c37f7aea732763947980600c6882ec908a54a0
MySQL 5.7.7-RC

 

 


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11月前
|
SQL 缓存 关系型数据库
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
132 0
|
11月前
|
SQL Oracle 关系型数据库
这次被坑惨了,MySQL的隐式转换导致了一个线上BUG
某一天,开发问我,为什么针对一个查询会有两条记录,且其中一条记录并不符合条件select * from tablea where xxno = 170325171202362928;xxno为 170325171202362928 和 170325171202362930的都出现在结果中。 一个等值查询为什么会有另外一个不同值的记录查询出来呢? 我们一起来看看究竟!
|
SQL 关系型数据库 MySQL
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
121 0
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
|
SQL 关系型数据库 MySQL
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(二)
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(二)
|
存储 固态存储 关系型数据库
MySQL 5.6 change buffer bug导致crash
Insert buffer 内部标识长度的位图没有正确更新,导致问题
139 0
|
SQL 运维 监控
一个诡异的MySQL查询超时问题,居然隐藏着存在了两年的BUG
一个诡异的MySQL查询超时问题,居然隐藏着存在了两年的BUG
165 0
|
SQL 关系型数据库 MySQL
看来,MySQL next-key lock 的 bug 并没有被修复!
在上一篇文章《MySQL next-key lock 加锁范围是什么?》中已经介绍了主键索引的加锁范围,现在来回顾一下
229 0
|
关系型数据库 MySQL Java
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。
219 0
【BUG日记】【MySQL】多个排序字段,是有优先级的,先来先优先。
|
SQL 运维 关系型数据库
MySQL 的这个 BUG,坑了多少人?
MySQL 的这个 BUG,坑了多少人?
163 0
MySQL 的这个 BUG,坑了多少人?