4. 数据库迁移基础:Online Schema Change 原理、pt-online-schema-change 与 gh-ost 工作机制
在微服务与高并发场景下,数据库表结构的变更(如添加索引、修改列类型)如果采用传统 LOCK=EXCLUSIVE 方式,会导致长时间写阻塞,进而引发上游 gRPC 调用超时与连接池耗尽。Online Schema Change(OSC)技术正是为了解决这一矛盾而诞生。本章将深入剖析 OSC 的核心原理,并对比两款主流工具——pt-online-schema-change(Percona Toolkit)与 gh-ost(GitHub Online Schema Transfomer)的工作机制。
4.1 Online Schema Change 核心原理
OSC 的核心思想是:不直接修改原表,而是通过创建一个影子表,在影子表上执行 DDL,然后通过触发器或 binlog 同步增量数据,最后通过原子性的表名切换完成变更。整个过程对业务流量几乎无感知。
核心三阶段:
- 准备阶段:创建与原表结构一致的空影子表,并在影子表上执行目标 DDL。
- 数据同步阶段:将原表的存量数据分批拷贝至影子表;同时持续捕获原表上的增量变更(INSERT/UPDATE/DELETE),并应用到影子表。
- 切换阶段:在确认数据一致后,通过原子性的
RENAME TABLE操作交换原表与影子表,完成最终变更。
4.2 pt-online-schema-change 工作机制
pt-online-schema-change(pt-osc)是 Percona Toolkit 中最常用的 OSC 工具。它基于 触发器(Trigger) 实现增量数据同步,架构简单且兼容性广。
4.2.1 核心工作流程
- 创建影子表:
CREATE TABLE _new LIKE original_table,并在影子表上执行目标 DDL。 - 安装触发器:在原表上创建 AFTER INSERT、AFTER UPDATE、AFTER DELETE 三个触发器,用于将增量变更实时同步到影子表。
- 分批拷贝存量数据:使用
INSERT LOW_PRIORITY INTO _new (...) SELECT ... FROM original_table FORCE INDEX(...) WHERE ...按主键范围分批拷贝。 - 等待与切换:当拷贝完成后,通过
RENAME TABLE original TO _old, _new TO original完成原子切换。 - 清理:删除原表(_old)和触发器。
4.2.2 优缺点分析
| 维度 | 说明 |
|---|---|
| 优点 |
|
| 缺点 |
|
性能陷阱:当原表写入量极大时,触发器会显著增加单次 DML 的响应时间。在 gRPC 调用链中,这种微小的延迟放大可能导致上游超时重试风暴。建议在变更前使用
--chunk-time 和 --sleep 参数控制拷贝速率。
4.3 gh-ost 工作机制
gh-ost 由 GitHub 开发,采用 无触发器(Triggerless) 架构,通过解析 MySQL binlog 来捕获增量变更,从根本上避免了触发器带来的性能问题。
4.3.1 核心工作流程
- 连接与配置:gh-ost 作为 MySQL 客户端连接到主库或从库,读取 binlog 流。
- 创建影子表:与 pt-osc 类似,创建
_gho影子表并执行 DDL。 - 读取 binlog 流:gh-ost 模拟一个从库,实时解析 binlog 中的行事件(Row-Based Replication),并将变更应用到影子表。
- 分批拷贝存量数据:使用
INSERT IGNORE INTO _gho (...) SELECT ... FROM original_table按主键范围拷贝。 - 原子切换:通过
RENAME TABLE original TO _ghc, _gho TO original完成切换。 - 清理:删除 changelog 表(_ghc)和影子表。
4.3.2 优缺点分析
| 维度 | 说明 |
|---|---|
| 优点 |
|
| 缺点 |
|
4.4 工具选型对比
| 对比维度 | pt-online-schema-change | gh-ost |
|---|---|---|
| 增量同步方式 | 触发器(Trigger) | Binlog 解析(Row-Based) |
| 对原表性能影响 | 较高(触发器增加 DML 开销) | 较低(无触发器,仅 binlog 读取) |
| MySQL 版本要求 | 5.5+ | 5.6+(需开启 binlog_row_image=FULL) |
| 主从复制要求 | 无特殊要求 | 需稳定复制,延迟敏感 |
| 暂停/恢复能力 | 有限(通过 --sleep 参数) | 原生支持(--throttle 命令) |
| 适用场景 | 低写入、兼容性优先 | 高写入、性能敏感 |
选型建议:
- 如果业务表写入量较小(< 1000 TPS),且 MySQL 版本较低,优先选择 pt-osc。
- 如果业务表写入量较大(> 5000 TPS),且对 gRPC 调用延迟敏感,强烈建议使用 gh-ost,避免触发器带来的 GC 停顿放大效应。
- 无论选择哪种工具,都应在变更前进行 压测,观察数据库 CPU、IO、复制延迟以及上游 gRPC 调用成功率。