MySQL 8.0/8.4执行DDL会丢数据?是,但影响有限

问题是有,但好在规避办法也比较简单,影响也有限。

先说解决办法,从简单到麻烦:

  1. 执行 ALTER TABLE 时,显式指定ALGORITHM=INSTANT/COPY,反正不要使用 INPLACE

  2. 适当调大 innodb_ddl_buffer_size 参数值,其默认值1MB,例如调大到100MB就可以应对大部分业务表的DDL操作场景。

  3. 利用 pt-oscgh-ost 等工具进行 Online DDL 操作。

  4. 在业务低谷时段执行DDL操作,有条件的话甚至可以在业务维护期间再执行DDL操作。

  5. 升级版本到已修复的 Percona 分支版本(下文会提到)。

问题来源

在 MySQL 8.0.27 版本中新增并行DDL功能后才“引入”了这个问题。目前在最新的 8.1.x/8.3.x/8.3.x/8.4.x/9.0.x/9.1.x 等版本中依然存在,预计到 MySQL 8.0.41 新版本会修复。

For online DDL operations, storage is usually the bottleneck. To address this issue, CPU utilization and index building has been improved. Indexes can now be built simultaneously instead of serially. Memory management has also been tightened to respect memory configuration limits set by the user.

详见:https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-27.html

触发原因:在INPLACE模式的DDL操作中重建主键索引时,因错误处理会略过部分记录,导致数据丢失。

触发条件:只影响INPLACE模式的DDL操作,不影响COPY和INSTANT模式的DDL操作。以下是几种常见的可能触发问题的DDL操作场景:

  • 场景1:ALTER TABLE ENGINE=INNODB 重整表空间操作,需要重建主键索引。

  • 场景2:ALTER TABLE ADD NEW-COL ...,ALGORITHM=INPLACE,新增列操作,因指定了INPLACE模式,需要重建主键索引。

其他例如INSTANT模式加新字段,增删索引则不会触发该问题。

关于该问题的详细解读详见几篇文章:

涉及到2个MySQL bug:

  • DDL 丢数风险:https://bugs.mysql.com/bug.php?id=115608

  • DDL 重复行报错:https://bugs.mysql.com/bug.php?id=115511

该问题核心就存在于如果涉及到需要用INPLACE算法重建主键索引的DDL操作,就需要在 innodb_ddl_buffer_size 用满后直接插入到 #sql-ibXXX 数据文件中,这个时候可能正在page的中间的某个位置,插入的时候会暂时放弃page上的mutex,并且保存游标到持久游标,然后插入数据,插入完成后再从持久游标恢复游标。这样做的目的可能是为了提高page修改的并发,但是这里保存和恢复持久游标却出了问题,主要是page中的数据可能出现修改,这种修改对应了前面的2个BUG:

  • Purge线程,清理del flag。

  • 其他线程INSERT了数据。

具体游标的保存和恢复出现的问题,可以参考Rex老师的文章 MySQL 8.4-LTS DDL会导致数据丢失

问题影响

目前该问题已知影响的版本列表如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值