TDSQL中修复的mysql内核bug

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 在TDSQL这两年多的开发工作中,我感觉很自豪的一件事是我修复了不少mysql-5.7.17和mariadb-10.1.9的内核bug,这些bug大多已经报告给了MySQL/MariaDB官方开发团队,在每个bug描述中我会贴出来bug报告的连接。本文将大略介绍这些bug的概况,我在将来会写更多文章详细介绍每个bug的具体问题分析以及解决思路。本文列出的所有bug都已经修复,经过验证可以正确工作并解决相关问题。这里先说一下为什么我要提交代码给mysql/mariadb官方开发团队,主要有一下几个好处:1. 官方开发者可以review我提交的patch,帮助完善patch,发现和解决之前

在TDSQL这两年多的开发工作中,我感觉很自豪的一件事是我修复了不少mysql-5.7.17和mariadb-10.1.9的内核bug,这些bug大多已经报告给了MySQL/MariaDB官方开发团队,在每个bug描述中我会贴出来bug报告的连接。本文将大略介绍这些bug的概况,我在将来会写更多文章详细介绍每个bug的具体问题分析以及解决思路。本文列出的所有bug都已经修复,经过验证可以正确工作并解决相关问题。

这里先说一下为什么我要提交代码给mysql/mariadb官方开发团队,主要有一下几个好处:

  1. 官方开发者可以review我提交的patch,帮助完善patch,发现和解决之前可能没有想到的问题。我自己做mysql内核开发和bug 修复时会跑mtr(mysql自带的测试包),确保所有测例通过,并且新增测例覆盖新增的功能和代码。不过即使如此,也可能有未考虑到的点,因此可以借助mysql/mariadb官方的力量。
  2. 将来在新版本合并代码会很容易,因为这些patch的改动已经在官方发布的新版本中了,就不需要再次合并了。
  3. 为开源软件做出贡献,这样的一种社区氛围长期来看对所有mysql用户都是好事。

下面就是每个bug的简介,主要介绍其症状和危害性。具体解决方法和分析过程以及修复代码patch请看bug链接的页面,我未来也会写文章做出更详细的讲解和分析。下文中经常提到的英文术语简介如下:

XA: 分布式事务处理

DML: 数据操作语言,比如SQL语言中的INSERT,UPDATE,DELETE,SELECT等语句。

Mutex:互斥量,操作系统基础功能

安装插件流程中的mutex死锁
执行install plugin语句时,负责插件状态互斥的一个mutex与负责全局变量状态互斥的mutex可能发生死锁。死锁一旦发生,mysqld就hang住了,所有连接都无法继续工作。我提交给mysql官方开发团队的bug报告如下:

Bug?#88693Mutex deadlock causing mysqld to hang and cease to work

https://bugs.mysql.com/bug.php?id=88693

Optimize table与DML语句的冲突
当执行optimize table时由大量的DML语句(比如delete)在执行时,innodb有可能crash在一个assert中,导致mysqld进程崩溃退出。详情请见我的bug报告:

Bug #88511 innodb assertion failure in table rename

https://bugs.mysql.com/bug.php?id=88511

percona 备机复制在特定事件序列情况下卡住
对于mysql-5.7的XA事务来说,在一个XA事务的任何位置中断slave IO线程的连接后都会出问题,导致备机sql线程陷入死循环,备机复制无法继续下去。我提交给mysql官方开发团队的bug报告如下:

Bug #87385 Partial external XA transactions are not rolled back correctly

https://bugs.mysql.com/bug.php?id=87385

MYSQL 客户端的AUTOCOMMIT状态位设置不准确
当global autocommit是0 时候 新开启一个mysql连接时,客户端返回的autocommit状态位是1,应该是0. mariadb和percona都有这个问题。这个bug对于绝大多数最终用户而言可能是无感知的,不过TDSQL的网关模块依赖于这个状态位来正确工作,因而我们发现并修复了这个bug。

我提交给mysql官方开发团队的bug报告如下:

Bug #87813 Incorrect autocommit status bit in server_status at connection startup

https://bugs.mysql.com/bug.php?id=87813

无法在AUTOCOMMIT=0时结束PREPARED状态的XA事务
如果一个连接的autocommit=0,然后执行XA COMMIT/XA ROLLBACK来结束一个事务,那么Mysql会报错并拒绝操作。报错信息:

ERROR 1399 (XAE07): XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state

这样导致PREPARED状态的XA事务在非autocommit 设置下无法被提交或者回滚,分布式事务处理机制无法正确工作。

我提交给mysql官方开发团队的bug报告如下:

Bug #87836 XA COMMIT/ROLLBACK rejected by non-autocommit session with no active transaction

https://bugs.mysql.com/bug.php?id=87836

percona XA事务提交和回滚的恢复机制
官方mysql-5.7的实现中,没有处理XA 事务分支的binlog + engine 恢复,包括XA PREPARE,XA COMMIT ... ONE PHASE以及XA COMMIT/XA ROLLBACK 提交的事务的恢复,mysql-5.7都没有实现binlog事务恢复机制,因而在各种灾难情况下会发生丢失XA事务,QQ号卖号平台数据不一致等致命问题。这些bug我们在TDSQL中都已经修复了。

这是一个巨大的开发任务,新增代码几千行,我提交给mysql官方开发团队的两个bug报告如下:

Bug #87560 XA PREPARE log order error in replication and binlog recovery

https://bugs.mysql.com/bug.php?id=87560

Bug #84297 Engine prepare executed after flush stage

https://bugs.mysql.com/bug.php?id=84297

Percona XA COMMIT/ROLLBACK事务的gtid管理
这类事件组(也就是一个xa事务的binlog的后半部分)在备机上面可能无法执行,因为主备切换的特殊时机下当前备曾是主机,已经执行过了。但是官方默认实现未考虑到这一点,就会导致备机可能无法连接到主机因为主机没有备机需要的gtid。此时的症状表现就是主备切换后,备机无法连上主机,产生反复连接和报错的循环,TDSQL在强同步模式下就无法运行了。这个bug已经修复,经过验证可以正确工作并解决相关问题。

Percona备机SQL线程执行XA_PREPARE_EVENT时,复制位置没有持久化
Percona备机SQL线程执行XA_PREPARE_EVENT时,复制位置没有持久化,于是备机crash然后重启之后,开始复制的位置就是错误的(会从更早的位置开始复制),就会导致复制卡住(比如要删除一个已经删除的行,或者更新时间找不到目标行,或者插入发生主键冲突)和数据不一致等严重问题。

我提交给mysql官方开发团队的bug报告如下:

Bug?#87389Replication position not persisted correctly for XA transactions

https://bugs.mysql.com/bug.php?id=87389

XA COMMIT事件没有被作为事务边界
MySQL-5.7的replication实现,依赖于一个事务状态分析对象,它根据扫描到的事件,维持一个当前事务状态,这个状态会被备机的复制机制使用。由于XA COMMIT这个事件没有被作为事务边界,就会导致很多XA相关的复制问题和bug。

我提交给mysql官方开发团队的bug报告如下:

Bug #87130 XA COMMIT not taken as transaction boundary

https://bugs.mysql.com/bug.php?id=87130

XA PREPARE与xtrabackup不能协同工作
主要原因是mysql执行XA PREPARE语句期间没有获取COMMIT全局意向锁,导致它不能被xtrabackup阻塞住,就可能发生xtrabackup备份的数据丢失了prepared事务的严重问题,导致数据不一致。

我提交给mysql官方开发团队的bug报告如下:

Bug #84442 XA PREPARE inconsistent with XTRABACKUP

https://bugs.mysql.com/bug.php?id=84442

XA COMMIT在其他连接中执行时与xtrabackup不能协同工作
如果XA COMMIT语句不是在当前XA事务所在的连接中执行的,而是当前连接断开后重新连接mysqld然后执行XA COMMIT,那么此时XA COMMIT不会获取全局COMMIT意向锁,也就不能被FTWRL阻挡住,于是就不能与xtrabackup正确地协同工作,导致数据不一致的严重问题。

我提交给mysql官方开发团队的bug报告如下:

Bug #84323 XA-COMMIT may not be blocked by FTWRL

https://bugs.mysql.com/bug.php?id=84323

mysqld 被mysqld.sock.lock阻挡而无法启动

mysql实现了一个防止重复启动mysqld的机制,就是在防止mysqld.sock的路径下面增加了一个mysql.sock.lock,这个文件里面记录着mysqld的进程号。当mysqld启动时刻,会检查这个文件内存储的进程号,向该进程发送一个信号0,如果发送成功,就认为这个进程是已经在运行的mysqld进程,于是当前正在启动的mysqld进程就退出了。

我们在做分布式事务的容灾测试期间,需要无数次反复kill掉和重启mysqld,偶尔会遇到mysqld无法启动的情况,报错就是 Another process with pid xxx is using unix socket file.

不过这个方法有个明显的漏洞,就是新的mysqld进程号向mysql.sock.lock里面存储的进程号XXX发送信号时,可能刚好有个进程的pid是这个数字XXX。这种事情发生的几率极低(因为linux 分配进程号的方式,并且我们的mysqld重新启动的间隔很短),但是不是不可能。所以我的改进方案就是在发送信号0 成功后,确认该进程的binary文件名是'mysqld'。如果检查仍然通过,那么还有可能这是另一个端口下的mysqld进程,尽管几率极低。所以我会做进一步的检查: 检查这个mysqld进程的启动参数中的--port=NUM 的NUM是当前正在启动中的mysqld进程的端口号。只有这些检查都通过了,才认为当前mysqld进程号确实是重复启动了,应该退出。

mariadb sleep时长不精确
这个是TDSQL的自研功能的bug修复。tdsql-mariadb-10.1.9 中,我们为了使sleep()函数避免出现因为机器时间被调整而导致sleep()无法按时返回的问题,重新实现了sleep()函数.

修改后,tdsql-mariadb-10.1.9提供了两种sleep()函数的实现,第一种是我的新的实现方案,可以避免机器时间被调整而导致sleep()无法按时返回的问题,并且精度与官方实现相同,默认使用该方案;另外,可以通过动态设置全局变量use_tdsql_sleep_func=0,来使用mariadb官方的默认sleep()函数实现。

MariaDB InnoDB表空间文件头标志字段bug
这是我在MariaDB官网上面提交的bug报告:https://jira.MariaDB.org/browse/MDEV-9581

这个bug的症状是MariaDB-10.1.9无法使用MariaDB-10.0.10产生的数据目录:当指定datadir为这样一个目录时,mysqld进程在启动过程中发现错误而退出了。也就是说,如果你之前在使用MariaDB-10.0.x,有一个数据目录,里面有你珍贵的数据,然后现在你打算使用MariaDB-10.1.x,你会痛苦地发现,MariaDB-10.1.x无法用原来的数据目录启动,也就无法使用mysql_upgrade来升级数据目录。虽然可以使用dump/load的方法来规避问题,但是在数据量很大的情况下,这样做非常耗时,效率很低。这个bug已经修复,经过验证可以正确工作并解决相关问题。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
SQL NoSQL AliSQL
MySQL RENAME hang问题分析与修复
问题现象:alter 过程 rename 文件一直失败,导致 crash。[Warning] InnoDB: Cannot rename file ./tradesupplymember/memberpropertyinfo_0024.ibd (space id 78102), retried 1000 times. There are either pending IOs or flushes 
512 0
MySQL RENAME hang问题分析与修复
|
3月前
|
SQL 关系型数据库 MySQL
(十八)MySQL排查篇:该如何定位并解决线上突发的Bug与疑难杂症?
前面《MySQL优化篇》、《SQL优化篇》两章中,聊到了关于数据库性能优化的话题,而本文则再来聊一聊关于MySQL线上排查方面的话题。线上排查、性能优化等内容是面试过程中的“常客”,而对于线上遇到的“疑难杂症”,需要通过理性的思维去分析问题、排查问题、定位问题,最后再着手解决问题,同时,如果解决掉所遇到的问题或瓶颈后,也可以在能力范围之内尝试最优解以及适当考虑拓展性。
182 3
|
5月前
|
关系型数据库 MySQL
蓝易云 - 如何修复MySQL中损坏的表
最后,为了防止数据丢失,定期备份数据是非常重要的。
151 3
|
SQL 存储 关系型数据库
【MySQL进阶-06】深入理解mysql的内核查询成本计算
【MySQL进阶-06】深入理解mysql的内核查询成本计算
397 0
|
6月前
|
SQL 存储 关系型数据库
Mysql内核查询成本计算
Mysql内核查询成本计算
|
关系型数据库 MySQL PHP
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
153 0
|
关系型数据库 MySQL API
如何修复“PHP 安装缺少 WordPress 所需的 MySQL 扩展”的错误?
在WordPress建站,WordPress定制开发过程中,开发者容易遇见“您的 PHP 安装似乎缺少 WordPress 所需的 MySQL 扩展”的错误提示,如果出现这样的情况,应该怎么办?北京六翼信息有限公司的开发工程师指出,要修复错误“您的 PHP 安装似乎缺少 WordPress 所需的 MySQL 扩展”,您需要确保您的 PHP 安装已正确安装和配置 MySQL 数据库驱动程序 (mysqlnd) 和 mysqli 扩展。只有这样,您才能恢复 WordPress 和 WordPress 数据库之间的正常连接,并让您的网站重新运行。
如何修复“PHP 安装缺少 WordPress 所需的 MySQL 扩展”的错误?
|
SQL 缓存 关系型数据库
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
215 0
下一篇
无影云桌面