主要观点总结
文章详细分析了在一次正常的 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 回放,以避免页分裂问题。
免责声明
免责声明:本文内容摘要由平台算法生成,仅为信息导航参考,不代表原文立场或观点。
原文内容版权归原作者所有,如您为原作者并希望删除该摘要或链接,请通过
【版权申诉通道】联系我们处理。