连载中 16/20

在线 DDL:分片环境的表结构变更

2026-07-26 · 2234 阅读 · 0 评论 · 0 赞

从一张表到三十二张表

MySQL 系列第 19 篇讲过单表大 DDL 的标准打法:用 gh-ost 或 pt-online-schema-change 做在线改表——影子表拷数据、增量回放、原子改名,全程不停写。分库分表之后,这套打法没有失效,只是工作量乘以了物理表的数量:一次加字段,8 库 32 表要跑 32 轮影子拷贝。好消息藏在坏消息里——每张物理表只有几百万行,单表拷贝从八小时缩到十几分钟;真正的难点从「怎么改一张大表」变成了「怎么协调三十二次小改表,全程线上无感」。

执行纪律:小步、串行、可停

分片环境的 DDL 变更纪律三条。金丝雀先行——先只改一个库的一张表,观察十五分钟:主从延迟、锁等待、同步链路都无恙,再继续;库内串行、库间并行——同一个实例上的表逐张改(共享 IO,并发只会互相拖慢),不同实例可以并行推进,总时长约等于最慢一库的耗时;可暂停可回退——gh-ost 支持暂停与终止,批处理脚本要有断点水位,变更中断后能从断点继续而不是从头再来。整套流程走下来,32 张表的加字段通常一个低峰夜就能安全完成。

真正的深坑:新旧结构共存

比执行更难的,是变更期间新旧表结构共存的问题:32 张表要改几个小时甚至一整夜,期间新旧结构同时在线——老结构的表没有新字段,新结构的表刚加上。这一刻如果有代码写了新字段的值,落到老结构的表直接报错。所以分片环境的 DDL 有铁律:结构变更和代码变更必须分两步发布:

第一步:先发「读写都不依赖新结构」的代码(兼容新旧两种结构)
第二步:全量完成 DDL(32 张表逐张改)
第三步:再发「开始使用新字段」的代码
// 顺序反了:新代码写新字段 → 落到未改的老结构表 → 直接报错

删字段反过来:先停用(代码不读写),再删除。改字段类型最凶险,走「加新列、双写、刷数据、切读、删旧列」的完整迁移小流程——本质上是一次微型数据迁移,第 14-15 篇的框架直接套用。

让 DDL 变成日常小事

治理做得好的团队,会把分片 DDL 从「应急项目」变成「日常流程」:变更脚本模板化(金丝雀、串行、断点、校验全内置),执行平台化(点按钮跑批、进度可视、异常自动暂停),评审规则化(字段评审在拆分设计期就把未来半年可能的扩展想清楚,减少变更次数本身)。最好的 DDL 是不需要 DDL——设计期多想一步,运营期少熬一夜。

结构变更的工程讲完,接下来是数据的日常代谢:历史数据堆积怎么办、归档怎么设计才安全——下一篇聊聊让主表保持轻盈的冷热分离。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#在线DDL#gh-ost#分片变更#新旧结构兼容#金丝雀

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞