暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

这么严重的bug还没有fix?

关注我,避免坑,运维 MySQL 不跑路,我比官方靠谱!

我前面发这篇文章《MySQL8.0.29出现重大bug,现已下架》火了,看起来很多都关注 bug 这个话题。

今天我要讲另外一个 bug,这个 bug 挺严重的,是由我的前同事发现和报告的。

我们知道前天 MySQL 官方发布了 5.7.40 和 8.0.31 版本,我查看 release note 发现这个 bug 并没有fix,然后我查看 bug report,确实没有 fix,链接如下:
https://bugs.mysql.com/bug.php?id=105761

这个bug是什么?对我们有什么影响?

这个 bug 非常严重!使用 MySQL5.7.36 及以上版本的 mysqldump 做数据库备份,有可能会得到一份数据不一致的备份。也就是你使用这个备份做数据库恢复会有数据丢失!!!

详细 bug 的描述如下: 我的同事做数据迁移的时候,执行了以下命令做逻辑备份。

mysqldump -u -p -h -P --single-transaction --set-gtid-purged=on -ER --databases db_name > 1.sql

关键点在于这两个参数 --single-transaction
--set-gtid-purged=on

我们数据库都是 gtid mode 的,而--set-gtid-purged 默认值是 auto,在 gtid mode 下等同于 on,也就是其实问题就是单用 --single-transaction 一个参数就能轻易模拟出 bug!

然后我们把这份数据导入到一个空的 MySQL 实例,建立复制关系,我们目的是做一个主从复制来实现实时的在线迁移数据。

然后,我们很快得到 sql thread 抛出了一个报错

Could not execute Update_rows event on table xxx.xxx; Can't find record in 'xxx.xxx', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000705, end_log_pos 174057460, Error_code: 1032

同事排查原因后,发现,这个备份居然有一个奇怪现象: 备份包含了主库过来的所有 gtid 编号,但数据却少了。
例如,gtid 编号是 1-100 个事务,但里面的数据(对应的SQL)只是 1 - 90 个事务的。
也就是数据和 gtid 编号对不上,这个备份和主库相比,丢失了 10 条事务。

同事查看了 5.7.36 的 release note,注意到 mysqldump 中的一个变化:"The dump file sequence has now been changed"(Bug #32843447)。也许是这个 bug fix 引入了这个新问题。

实际后面证实他的直觉上的猜想被 Percona 大佬确定是对的。

既然认为新版 mysqldump 有问题,同事马上测试了 mysqldump 5.7.33,发现没有这个 bug。同时也测了 当时最新的 8.0 版本,mysqldump 8.0.27 版本,发现也没有这个 bug。

结合 bug report 网页里各种人的舌战,这个 bug 大概是这样:
发生在版本号大于 5.7.36 或以上的 mysqldump 程序上,使用这些版本的 mysqldump 并且使用--single-transaction
--set-gtid-purged=on
参数,做数据库备份会备份出一份数据一致性有问题的备份。这个 bug 不涉及 8.0。

我对官方的处理不满意

  1. 技术支持人员一开始定位这个 bug 的严重等级搞错了。这个 bug 会导致数据不一致,这是很灾难的事情啊,居然定为 S3 (Non-critical) 级别的 bug了。后面有其他人反馈这个 bug 很严重,他们才意识到,才改的 S2 (Serious),所以现在都过了 4 个版本,到 5.7.40 了,此 bug 居然还没有 fix !
  2. 官方测试说他们测了 8.0 也有这个问题,我自己没有测试,我相信我同事的测试结果,认为此 bug 只影响 5.7.36+ 的 mysqldump。anyway,因为这个 bug 的存在,尽量用 xtrabackup 来做备份/迁移或者用低版本 mysqldump 来做吧。
  3. Percona 已经有大佬都提供了补丁了,干嘛还不合并,别人 Percona server 5.7.36 版本开始就 fix 了。(Percona 大佬也认为不涉及 8.0,这个 MySQL 官方技术支持是临时工吧?)
  1. MySQL 官方为了拖延这个 bug fix 时间,居然采用一个很奇葩的做法,改官方文档。。。说--single-transaction
    --set-gtid-purged=on
    不能一起用,会导致备份数据不一致。

越来越好笑了,那怎么解释 mysqldump 5.7.33 可以一起用,但备份数据是一致的?

说到底,问题的根源是,旧的 mysqldump 是备份开始时获取 @@GLOBAL.GTID_EXECUTED,而新 mysqldump 是在备份结束才获取 @@GLOBAL.GTID_EXECUTED 的。

前者的才是对的逻辑: mysqldump 一开始整个快照,获取@@GLOBAL.GTID_EXECUTED,备份的是这个快照点位的数据的,不备份备份持续期间的增量数据的。gtid 编号告诉你份的一致性是你开始备份的那个时间点,实际上备份的数据也是你开始备份的那个时间点,是一致的。

现在问题是,官方新 mysqldump 通过 gtid 编号告诉你备份的一致性是结束备份时的那时间点,但实际里面的数据只备份到备份开始那个时间点。

写在最后

为什么官方会搞成这样?整个故事建议大家还是看看 bug report 原文吧,等下个版本官方答复吧,我已经没眼看了。如果这篇文章挽救了你们公司的数据库,希望打赏个让我知道。

参考

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


最后修改时间:2023-05-26 16:27:27
文章转载自芬达的数据库学习笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论