OSC (Online Schema Change) 指南
SQL-Platform-Pro 集成了多种在线 DDL 变更方案,根据数据库类型、版本、环境自动推荐最优策略。
一、为什么需要 OSC?
传统 ALTER TABLE 在大表上执行时会锁表,导致业务不可用:
| 问题 |
影响 |
| 锁表 |
MDL 写锁阻塞所有读写请求 |
| 全表拷贝 |
按 row copy 重建表,耗时随数据量线性增长 |
| 不可暂停 |
一旦开始无法中途停止,只能 kill |
| 主从延迟 |
大事务导致 binlog 积压,从库大幅延迟 |
OSC 工具通过创建影子表 + 增量同步的方式,实现不锁表的在线变更。
二、平台支持的三种 DDL 方案
1. Native DDL (MySQL 官方)
MySQL 8.0+ 内置的 INSTANT DDL 能力,零拷贝、秒级完成。
| 项目 |
说明 |
| 最低版本 |
MySQL 8.0.12 |
| 原理 |
只修改数据字典元数据,不拷贝数据 |
| 支持的 DDL |
ADD COLUMN (末尾)、DROP COLUMN、ADD INDEX、DROP INDEX、MODIFY 默认值 |
| 不支持的 |
CHANGE COLUMN 类型、ADD COLUMN 指定位置 (8.0.28 以下)、RENAME COLUMN |
| 语法 |
ALTER TABLE t ADD COLUMN c INT, ALGORITHM=INSTANT; |
优势:最快、最简单、零风险
劣势:部分 DDL 类型不支持,回退到 INPLACE/COPY 时仍可能锁表
2. gh-ost (GitHub 开源)
GitHub 开发的在线 DDL 工具,通过 binlog 流式同步实现零锁变更。
| 项目 |
说明 |
| GitHub |
https://github.com/github/gh-ost |
| 原理 |
创建影子表 → 拷贝数据 → 通过 binlog 实时同步增量变更 → 原子 cut-over 切换 |
| 依赖 |
MySQL binlog_format=ROW, binlog_row_image=FULL |
| 特点 |
无触发器、可暂停/恢复、实时进度输出、支持回滚 |
优势:
- 不使用触发器,对数据库性能影响最小
- 可随时暂停 (
--postpone-cut-over-flag-file)
- 实时进度 (
Copy: 100000/500000 20.0%)
- 支持回滚 (保留旧表)
劣势:
- 需要开启 binlog
- 需要安装 gh-ost 二进制
- 单机 MySQL 需加
--allow-on-master
3. pt-online-schema-change (Percona)
Percona Toolkit 中的 OSC 工具,通过触发器同步增量变更。
优势:兼容性好,MySQL 5.1+ 都支持
劣势:触发器对高并发场景性能影响较大
三、方案对比
| 维度 |
Native INSTANT |
gh-ost |
pt-osc |
| 执行速度 |
⚡ 秒级 |
🔄 数据量相关 |
🔄 数据量相关 |
| 锁表风险 |
❌ 无 |
❌ 无 (cut-over 瞬间 <1s) |
❌ 无 (cut-over 瞬间 <1s) |
| 性能影响 |
无 |
低 (binlog 解析) |
中 (触发器开销) |
| 可暂停 |
N/A |
✅ |
✅ |
| 进度可见 |
N/A |
✅ 百分比 |
❌ |
| 支持回滚 |
❌ |
✅ 保留旧表 |
✅ 保留旧表 |
| Binlog 要求 |
无 |
ROW + FULL |
无 |
| MySQL 版本 |
8.0.12+ |
5.6+ |
5.1+ |
| 云数据库 |
✅ 推荐 |
⚠️ 需开 binlog |
⚠️ 需开 binlog |
四、场景推荐矩阵
按数据库类型
| 场景 |
推荐方案 |
原因 |
| AWS Aurora MySQL + 任何 DDL |
Native DDL |
Aurora 原生 DDL 已深度优化,开 binlog 影响性能和存储成本 |
| 阿里云 PolarDB MySQL + ADD/DROP COLUMN |
Native DDL |
PolarDB 自带 Instant DDL,秒级完成 |
| 阿里云 RDS MySQL + 大表 DDL |
gh-ost + --aliyun-rds |
RDS 权限受限,gh-ost 有专用适配模式 |
| 自建 MySQL 8.0+ + 小表 |
Native INSTANT |
版本支持,秒级完成,无需额外工具 |
| 自建 MySQL 8.0+ + 大表生产 |
gh-ost |
可暂停+进度可见+回滚安全 |
| 自建 MySQL 5.7 + 大表 |
gh-ost |
5.7 无 INSTANT,必须用 OSC 工具 |
按环境
| 场景 |
推荐方案 |
原因 |
| 开发/测试环境 |
Native DDL |
数据量小,即使 COPY 也很快 |
| 预发布环境 |
gh-ost dry-run |
先预检,确认变更可行性 |
| 生产环境 + 表 < 10万行 |
Native DDL |
小表无风险 |
| 生产环境 + 表 > 10万行 |
gh-ost |
行数超阈值,安全起见用 OSC |
| 生产环境 + 表 > 1000万行 |
gh-ost + chunk_size=500 |
大表限流,降低对线上影响 |
按 DDL 类型
| DDL 操作 |
MySQL 8.0+ INSTANT |
推荐 |
ADD COLUMN (末尾) |
✅ 支持 |
Native INSTANT |
DROP COLUMN |
✅ 支持 (8.0.12+) |
Native INSTANT |
ADD INDEX |
❌ INPLACE |
gh-ost (大表) 或 Native INPLACE (小表) |
DROP INDEX |
❌ INPLACE |
Native INPLACE (不拷贝数据) |
MODIFY COLUMN 类型 |
❌ COPY |
必须 gh-ost |
CHANGE COLUMN |
❌ COPY |
必须 gh-ost |
ADD COLUMN (指定位置 AFTER) |
✅ 支持 (8.0.29+) |
版本够用 Native,否则 gh-ost |
DROP PRIMARY KEY |
❌ COPY |
必须 gh-ost |
五、平台配置说明
平台通过 system_settings 表管理 gh-ost 策略,共 13 项配置:
基础配置
| 配置项 |
Key |
默认值 |
说明 |
| 全局开关 |
ghost_enabled |
false |
关闭后所有 gh-ost API 返回 403 |
| 默认执行模式 |
ghost_default_mode |
dry_run |
dry_run=仅预检, execute=真实执行 |
| OSC 优先级 |
ghost_osc_priority |
native_first |
native_first / ghost_first / ghost_only |
| 环境模式 |
ghost_env_mode |
development |
development=Native优先, production=强制gh-ost |
| 云数据库类型 |
ghost_cloud_type |
self_hosted |
self_hosted / aliyun_rds / polardb / aws_aurora |
自动触发条件
| 配置项 |
Key |
默认值 |
说明 |
| 行数阈值 |
ghost_auto_trigger_rows |
10 (万) |
表行数超过此值自动推荐 gh-ost |
| DDL 类型 |
ghost_auto_trigger_ddl |
ADD COLUMN,... |
匹配这些 DDL 类型自动触发 |
执行参数
| 配置项 |
Key |
默认值 |
说明 |
| 二进制路径 |
ghost_path |
/usr/local/bin/gh-ost |
gh-ost 可执行文件路径 |
| Chunk Size |
ghost_default_chunk_size |
1000 |
每批拷贝行数 |
| 最大负载 |
ghost_max_load |
Threads_running=25 |
超过则限流 |
| 临界负载 |
ghost_critical_load |
Threads_running=50 |
超过则立即终止 |
| 复制延迟 |
ghost_max_lag_millis |
1500 |
超过此延迟限流 (ms) |
| 允许主库执行 |
ghost_allow_on_master |
true |
单机/无从库需开启 |
六、API 接口
智能分析 (推荐第一个调用)
Dry-Run (预检,不实际执行)
Execute (真实执行变更)
查看配置
任务状态
七、gh-ost 最佳实践
生产环境执行流程
大表参数建议
| 表行数 |
chunk_size |
max_load |
说明 |
| < 100万 |
1000 |
Threads_running=25 |
默认配置 |
| 100万-1000万 |
500 |
Threads_running=20 |
适当限流 |
| > 1000万 |
200-500 |
Threads_running=15 |
严格限流 |
| > 1亿 |
100 |
Threads_running=10 |
极限限流 + 业务低峰执行 |
紧急暂停/恢复
gh-ost 支持运行时暂停,通过 flag 文件控制:
回滚方案
gh-ost 执行完成后旧表保留(_old 后缀),确认无问题后手动删除:
八、云数据库特殊说明
AWS Aurora MySQL
| 项目 |
说明 |
| 推荐方案 |
Native DDL |
| binlog |
默认关闭,开启影响性能和存储成本 |
| 如果必须用 gh-ost |
需在 Cluster Parameter Group 开启 binlog + binlog_format=ROW + binlog_row_image=FULL |
| 平台 flag |
ghost_cloud_type=aws_aurora → 自动加 --aws |
阿里云 PolarDB MySQL
| 项目 |
说明 |
| 推荐方案 |
Native DDL (PolarDB 自带 Instant DDL) |
| DDL 优化 |
大部分 ALTER 秒级完成,无需 OSC 工具 |
| 如果必须用 gh-ost |
需开启 binlog,官方 FAQ 确认支持 |
阿里云 RDS MySQL
| 项目 |
说明 |
| 推荐方案 |
小表 Native,大表 gh-ost |
| gh-ost 适配 |
需加 --aliyun-rds flag |
| 权限 |
RDS 不授 SUPER 权限,gh-ost 有专门适配 |
| 平台 flag |
ghost_cloud_type=aliyun_rds → 自动加 --aliyun-rds |
自建 MySQL
| 项目 |
说明 |
| 推荐方案 |
MySQL 8.0.12+ 小表 Native,大表 gh-ost |
| 前置条件 |
binlog_format=ROW + binlog_row_image=FULL |
| 单机环境 |
需加 --allow-on-master(平台默认开启) |
| 主从环境 |
优先在从库执行,主库自动同步 |