跳至正文
StackBug
返回

生产环境大表新增字段的风险与最佳实践

生产环境大表新增字段的风险与最佳实践

一、为什么要谨慎对待生产 DDL(尤其是大表)

表结构变更(DDL)在生产环境不可避免。但在千万级/亿级大表上跑原生 ALTER TABLE,代价可能很高:

建议不在生产上直接用 MySQL 原生 DDL,优先选用 在线 Schema 变更工具 来降低风险。

二、典型事故回顾(缩写版)

在核心大表aigc_lesson上执行:

ALTER TABLE aigc_lesson ADD error_message TEXT NULL COMMENT '错误信息';

执行期间数据库整体变慢、部分请求超时。根因:不同 MySQL 版本/引擎特性下,添加TEXT/BLOB字段常会触发表重建或重写,形成长时间锁与 I/O 压力。

类型、位置、版本都影响算法路径;看似”在线”的 DDL,条件不满足时就会退化为 COPY。


三、原生 DDL 的不确定性

  1. 算法不可控:ALGORITHM=INPLACE/INSTANT的可用性 强依赖版本与具体变更;条件不满足时会退化为COPY
  2. 大字段风险更高:TEXT/BLOB等类型在不少组合场景下难以真正在线,极易触发表重建。
  3. 失败成本高:执行中断或失败,回滚与清理代价大;长时间阻塞期间,业务易雪崩。

如果必须走原生 DDL,请确保版本明确且在测试环境验证 “会因 INSTANT/INPLACE 成功、且 LOCK=NONE”,否则不要在生产尝试。


四、推荐做法:工具化在线变更

方案 A:pt-online-schema-change(pt-osc)

原理:建影子表 → 触发器同步增量 → 分批拷贝历史数据 → 原子切换表名。 优点:业务可写、锁极短、可限速、可随时暂停/中止。

示例命令(可直接套用并按需微调):

pt-online-schema-change \
  --alter "ADD COLUMN error_message TEXT NULL COMMENT '错误信息'" \
  --execute \
  --user=root --password='***' --host=127.0.0.1 --port=3306 \
  D=mydb,t=aigc_lesson \
  --charset=utf8mb4 \
  --chunk-time=0.5 \
  --max-load Threads_running=50 \
  --critical-load Threads_running=100 \
  --check-interval=2

小贴士:先跑--dry-run验证流程,再用--execute正式执行;业务繁忙时可调小--chunk-time或收紧--max-load


方案 B:gh-ost

原理:通过 binlog 捕获增量变化(非触发器),对大表影响更小、灰度能力更强。 常见前提:binlog 开启、权限与复制链路允许读取 binlog(详情以各自环境为准)。

示例命令:

gh-ost \
  --user="root" \
  --password="***" \
  --host="127.0.0.1" \
  --database="mydb" \
  --table="aigc_lesson" \
  --alter="ADD COLUMN error_message TEXT NULL COMMENT '错误信息'" \
  --allow-on-master \
  --max-lag-millis=1500 \
  --cut-over=default \
  --exact-rowcount \
  --conflict-free-interval=5s \
  --execute

小贴士:先在从库或影子环境做演练(如用--test-on-replica等组合思路),确认复制延迟与切换行为可控。


五、工具化对比速览

维度MySQL 原生 DDLpt-osc / gh-ost
锁表风险高,可能长时间锁极低,仅切换瞬间需短锁
线上影响不可控,退化 COPY 极痛可限速,可暂停,影响可控
空间与 I/O可能倍增可平滑迁移、渐进占用
监控与止损缺乏自带限流/中止/进度监控
TEXT/BLOB易触发表重建更稳,仍需演练与监控

六、落地流程(一页清单)

上线前

评估影响:行数、数据量、索引、存储/磁盘余量、复制延迟预算

SELECT table_schema, table_name,
       data_length + index_length AS bytes
FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='aigc_lesson';

执行中

执行后


七、何时谨慎考虑原生 DDL(少数场景)

即便如此,仍建议 先演练 并在 低峰 执行。


八、常见坑位与规避


九、总结


分享到:

上一篇
为什么 Elasticsearch 精确查询要用 keyword?
下一篇
使用 elasticdump 跨集群迁移 Elasticsearch 索引的完整指南