今天看啥  ›  专栏  ›  得物技术

破解gh-ost变更导致MySQL表膨胀之谜|得物技术

得物技术  · 公众号  · 数据库  · 2025-09-17 18:30
    

主要观点总结

文章详细分析了在一次正常的 DDL 变更完成后,MySQL 数据库的表膨胀和统计信息差异巨大的问题。问题根源在于当前 DDL 变更流程叠加单行记录过大时,会触发 MySQL 页分裂的一个缺陷,导致每个页只存储一条记录,造成存储空间膨胀。同时,由于统计信息收集算法中对单个页的唯一值进行了减1操作,当每个页只存储一条数据时,导致统计信息严重偏差。文章还探讨了统计信息与慢 SQL 之间的关联关系,并给出了临时和长期的解决方案。

关键观点总结

关键观点1: 问题背景

业务同学在 OneDBA 平台进行一次正常 DDL 变更完成后,发现 SQL 出现慢查,且变更后的表比变更前的表存储空间膨胀了几乎 100%。

关键观点2: 索引结构

InnoDB 表的索引组织为 B+tree 结构,数据存储在叶子节点,而非叶子节点存储子页的最小 key 和子页号。

关键观点3: 页(page)和溢出页

页默认 16K 大小,当一条记录 >8k 时会溢出存储,当前页只存储溢出页面的地址。

关键观点4: 页面分裂

随着表数据变化,对记录的新增、更新、删除时,在 B+tree 中通过页面分裂和页面合并调整存储结构。

关键观点5: 当前DDL变更机制

MySQL 结构变更模块基于全量数据复制+增量 binlog 回放,以确保无锁化和减少主从数据延迟。

关键观点6: 变更后表膨胀原因

在 DDL 变更过程中,新插入的记录可能会先写入到表中,然后复制数据后写入到表中,叠加单行记录过大时,触发 MySQL 页分裂的一个缺陷,导致每个页只存储一条记录。

关键观点7: 统计信息差异巨大原因

统计信息收集算法对单个页的唯一值进行了减1操作,当每个页只存储一条数据时,导致统计信息严重偏差。

关键观点8: 统计信息与慢SQL的关联关系

MySQL 在评估扫描行数时不再依赖统计信息数据,而是使用 index dive 采样算法实时获取数据,但部分 SQL 可能会受到统计信息偏差的影响。

关键观点9: 临时解决方案

在低峰期对表执行原生 alter table xxx engine=innodb 语句,MySQL 内部重新整理了表空间数据,相关问题恢复正常。

关键观点10: 长期解决方案

调整 DDL 变更流程,先执行全量数据复制,然后再进行增量 binlog 回放,以避免页分裂问题。


免责声明

免责声明:本文内容摘要由平台算法生成,仅为信息导航参考,不代表原文立场或观点。 原文内容版权归原作者所有,如您为原作者并希望删除该摘要或链接,请通过 【版权申诉通道】联系我们处理。

原文地址:访问原文地址
总结与预览地址:访问总结与预览
推荐产品:   推荐产品
文章地址: 访问文章快照