【背景】 15 年 DBA,管过从 10 亿行的交易库到几十套只读链路。每次大表 DDL(加列、改列类型、加二级索引)都是事故高发区:锁表卡写、主从延迟飙到分钟级、复制线程被 DDL 拖死、回滚比做变更还疼。社区里热榜在聊连接池和超时,但我觉得数据库变更这条「暗线」的坑同样深,而且我们这帮 DBA 内部也没共识。
【常见分歧 / 几种做法】
- 原生 Online DDL(MySQL 5.6+ ALGORITHM=INPLACE/INSTANT):省事、无影子表、无额外 IO;但大表 ADD COLUMN 走 INPLACE 仍要扫全表(5.7 的 INSTANT 只覆盖部分场景),执行期间主从延迟、md5 校验、kill 掉重来都是真实痛点。
- pt-online-schema-change:老 DBA 的肌肉记忆;靠触发器 + 影子表,优点是进度可控、可限速(--max-load)、支持
--no-drop-old-table留后路;缺点是触发器在业务高峰会放大写延迟,且对--chunk-time/--chunk-size的调参非常吃经验。 - gh-ost:无触发器,直接监听 binlog 做增量同步,对线上写路径几乎零侵入,进度展示和 resume 体验都更好;但它依赖一个「能写 binlog 的账号」,多主/特殊复制拓扑下要额外验证,且回滚语义和 pt-osc 不一样(靠 rename 回切)。
- 分批 DML + 双写 + 切表:最重但最稳,适合「改列类型」这种没法原地改的场景;代价是 2~4 周的双写窗口和一次全量数据校验。
- 干脆不在线上做,选低峰窗口停写:听起来最土,但在一些金融/支付场景反而是最省心的——停写 30 分钟换一周的稳定性预算。
【我的倾向与理由】 我的默认顺序是:
- 能用 INSTANT / INPLACE 且预估执行时间 < 主从延迟 SLO 容忍窗口 → 直接原生,别引第三方工具;
- 表 > 5 亿行或业务写 QPS > 2000 → 首选 gh-ost(避开触发器),pt-osc 作为 gh-ost 跑不通(拓扑/权限)时的 fallback;
- 改列类型这类无法原地改的 → 双写 + 校验 + 切表,拒绝「一把梭」;
- 金融级核心表 → 低峰停写,别用工具换「看起来在线」的假象。 理由只有一条:变更工具只是手段,风险预算才是目的。引入 gh-ost/pt-osc 的隐性成本是「多一个组件要运维、多一套回滚路径要演练」,当表不大、窗口够时,原生 DDL 反而风险面最小。
【想听大家在什么场景下怎么选】
- 你们线上大表 DDL 的默认路径是什么?有没有「踩了 gh-ost 才回头用 pt-osc」或反过来的真实案例?
- gh-ost 在 K8s + 自建 MySQL(无云厂商 DMS)环境,你们怎么解决 binlog 监听账号的权限最小化?
- 有没有人做过「同一张表先用 pt-osc 试跑到 30%,发现写延迟涨了,切回 gh-ost 续跑」这种混合路径?工具间迁移的坑在哪?
- 低峰停写这条路,你们团队内部立项时怎么说服业务接受「非在线变更」?
欢迎贴你们的表规模、QPS、执行时长、主从延迟曲线,具体数据比抽象结论有用。
0赞
0收藏
0楼层