在线DDL变更的痛点
MySQL 8虽然支持了ALGORITHM=INPLACE的DDL,但在大表(千万行以上)场景仍然面临锁等待和主从延迟风险。加字段、改索引这类操作,Online DDL期间的主库写负载和从库回放延迟足以拖垮整个业务链路。生产环境必须用第三方工具做影子表切换,实现接近零停机的Schema变更。
pt-online-schema-change工作原理
Percona Toolkit的pt-osc是最成熟的方案,核心流程:
- 创建与原表结构相同的影子表
- 在影子表上执行DDL
- 创建三个Trigger(INSERT/UPDATE/DELETE)将原表的增量变更同步到影子表
- 分批从原表拷贝数据到影子表
- RENAME TABLE原子切换原表和影子表
- 删除旧表和Trigger
加字段操作示例:
pt-online-schema-change --host=10.0.0.1 --port=3306 --user=admin --password='S3cureP@ss' --alter="ADD COLUMN last_login_time DATETIME DEFAULT NULL COMMENT '最后登录时间', ADD INDEX idx_last_login(last_login_time)" --database=production --table=users --max-load=Threads_running=100 --critical-load=Threads_running=200 --chunk-size=1000 --chunk-time=0.5 --recursion-method=processlist --check-replication-filters --check-slave-lag=h=slave1,port=3306 --max-lag=2s --execute
关键参数解析:
--max-load:达到100个并发线程时暂停拷贝--critical-load:达到200个并发线程时终止操作--chunk-time=0.5:动态调整每批数据量,目标0.5秒拷完一批--max-lag=2s:从库延迟超2秒暂停拷贝
gh-osc工作原理与差异
GitHub开源的gh-osc不用Trigger做增量同步,而是通过解析binlog回放到影子表。这避免了Trigger带来的性能开销和元数据锁问题。
gh-ost --host=10.0.0.1 --port=3306 --user=admin --password='S3cureP@ss' --database=production --table=users --alter="ADD COLUMN last_login_time DATETIME DEFAULT NULL, ADD INDEX idx_last_login(last_login_time)" --max-load=Threads_running=100 --critical-load=Threads_running=200 --chunk-size=1000 --max-lag-millis=2000 --allow-on-master --execute
两个工具的场景选型
| 对比维度 | pt-osc | gh-ost |
|---|---|---|
| 增量同步方式 | Trigger | Binlog解析 |
| 对主库性能影响 | 较高(Trigger开销) | 较低 |
| 外键支持 | 支持 | 不支持 |
| 要求binlog格式 | 无要求 | ROW格式 |
| 单主机模式 | 支持 | 需–allow-on-master |
| 暂停恢复 | 信号控制 | 信号+标记文件 |
| RENAME风险 | 两个RENAME | 单RENAME(更安全) |
选型建议:
- 表有外键约束 → pt-osc
- 主库写入量极大 → gh-ost
- binlog格式不是ROW且无法修改 → pt-osc
- 有暂停/恢复的精细控制需求 → gh-ost
变更操作的标准流程
生产环境DDL变更必须遵循以下步骤:
# 1. 在测试环境验证DDL语法
mysql -h test-db -e "SHOW CREATE TABLE users\G"
pt-online-schema-change --dry-run --alter="..." ...
# 2. 在从库验证变更影响
# 先在延迟从库执行,观察主从延迟
# 3. 生产环境执行,开启监控
pt-online-schema-change --execute --alter="..." ... &
# 另开终端监控
watch -n 5 'mysql -e "SHOW PROCESSLIST" | grep pt_osc'
# 4. 变更完成后的验证
mysql -e "SHOW CREATE TABLE users\G"
mysql -e "SELECT COUNT(*) FROM users"
# 检查Trigger是否已清理
mysql -e "SHOW TRIGGERS FROM production LIKE 'users'"
大表DDL不是难在技术实现,难在操作纪律。变更窗口审批、从库延迟监控、回滚方案准备——这三样缺一不可。工具再好,操作不规范一样出事故。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql8-da-biao-zai-xian-ddl-bian-geng-ptosc-yu-ghost-gong/