Files
opsxsql/docs/OSC-GH-OST-GUIDE.md
T
logan ce8bb9710b docs: OSC/gh-ost 完整技术文档
- 为什么需要OSC + 三种方案对比(Native/gh-ost/pt-osc)
- 场景推荐矩阵: 按数据库类型/环境/DDL类型
- 平台13项配置说明
- API接口文档(analyze/dry-run/execute/status)
- gh-ost最佳实践(执行流程/大表参数/暂停恢复/回滚)
- 云数据库特殊说明(Aurora/PolarDB/RDS/自建)
2026-05-27 00:54:52 +08:00

310 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 工具,通过**触发器**同步增量变更。
| 项目 | 说明 |
|---|---|
| **官网** | https://docs.percona.com/percona-toolkit/pt-online-schema-change.html |
| **原理** | 创建影子表 → 拷贝数据 → 通过 AFTER INSERT/UPDATE/DELETE 触发器同步增量 |
| **依赖** | MySQL 5.1+ |
| **状态** | 平台预留接口,暂未集成 |
**优势**:兼容性好,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 接口
### 智能分析 (推荐第一个调用)
```bash
POST /api/v1/ghost/analyze
{
"instance_id": 3,
"database": "mydb",
"table": "users",
"alter": "ADD COLUMN phone VARCHAR(20) DEFAULT ''"
}
# 响应
{
"enabled": true,
"ddl_types": ["ADD COLUMN"],
"needs_osc": false,
"recommended_tool": "native",
"reason": "开发/测试环境,建议使用 Native DDL",
"mysql_version": "8.4.9",
"supports_instant": true,
"cloud_type": "self_hosted",
"table_rows": 150000,
"config": { ... }
}
```
### Dry-Run (预检,不实际执行)
```bash
POST /api/v1/ghost/dry-run
{
"instance_id": 3,
"database": "mydb",
"table": "users",
"alter": "ADD COLUMN phone VARCHAR(20) DEFAULT ''"
}
```
### Execute (真实执行变更)
```bash
POST /api/v1/ghost/execute
{
"instance_id": 3,
"database": "mydb",
"table": "users",
"alter": "ADD COLUMN phone VARCHAR(20) DEFAULT ''"
}
```
### 查看配置
```bash
GET /api/v1/ghost/config
```
### 任务状态
```bash
GET /api/v1/ghost/tasks
GET /api/v1/ghost/status/:taskId
```
---
## 七、gh-ost 最佳实践
### 生产环境执行流程
```
1. POST /ghost/analyze → 确认推荐方案
2. POST /ghost/dry-run → 预检连接/权限/binlog
3. 确认 dry-run 成功
4. POST /ghost/execute → 真实执行
5. GET /ghost/status/:id → 监控进度
```
### 大表参数建议
| 表行数 | 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 文件控制:
```bash
# 暂停 cut-over (数据同步继续,不切换表)
touch /tmp/gh-ost.mydb.users.postpone
# 恢复
rm /tmp/gh-ost.mydb.users.postpone
```
### 回滚方案
gh-ost 执行完成后**旧表保留**(`_old` 后缀),确认无问题后手动删除:
```sql
-- 确认新表数据正确后,删除旧表
DROP TABLE IF EXISTS `users_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`(平台默认开启) |
| **主从环境** | 优先在从库执行,主库自动同步 |