在数据库运维过程中,对字段类型做变更是令人非常头痛的一件事,在传统MySQL中,一般需要借助外部的Online DDL工具(比如pt-osc
目前,有许多开源的无锁变更工具为用户提供了平滑进行列类型变更的解决方案,有效规避了锁表问题。其中较为知名的工具包括 GitHub 开源项目
- 创建一张与原表结构一样的临时表
- 将具体变更操作应用到临时表上
- 将存量数据拷贝到临时表中
- 同步增量修改数据到临时表中
- 交换原表和临时表,完成变更
在增量数据同步方面,gh-ost 与 pt-osc 实现的方式有所不同,gh-ost 采用 binlog 订阅进行回放,而 pt-osc 采用的是利用触发器进行增量双写,但两种增量方案都并不完美。比如:gh-ost增量回放和存量数据拷贝共用一个线程,速度慢,但侵入性小,在业务流量较大时会出现binlog追不上,导致永远无法完成。比如:pt-osc引入触发器会增加死锁风险,一旦遇到DDL执行中断退出,存在触发器残留,触发器无法暂停等问题。
PolarDB-X v2.4.1版本,全面提供了内核原生的无锁变更能力,可以更好的支持类似字段类型变更的场景,重点在增量数据同步、智能限速、多版本元数据切换上,提供了更多不一样的设计,更多可以参考 PolarDB-X 原生无锁变更,比 gh-ost 更快、更稳定
PolarDB-X 新增DDL算法类型,OMC算法(全称为:Online Modify Column,在线变更列类型)。
语法格式:
ALTER TABLE tbl_name
alter_option [, alter_option] ...
ALGORITHM = OMC实际demo例子:
# 创建测试表
CREATE TABLE t1(a int primary key, b tinyint, c varchar(10)) partition by key(a);
# 修改t1表中b列和c列的列类型
ALTER TABLE t1 MODIFY COLUMN b int, MODIFY COLUMN c varchar (30), ALGORITHM=OMC;
# 修改t1表中b列的名称和类型,并在该列后面增加一个bigint类型的e列
ALTER TABLE t1 CHANGE COLUMN b d int, ADD COLUMN e bigint AFTER d, ALGORITHM=OMC;我们也为PolarDB-X OMC算法,与gh-ost/pt-osc做了完整的性能对比,比如:以sysbench oltp_read_write压测为背景流量,执行在线列变更
ALTER TABLE MODIFY COLUMN `sbtest1` MODIFY COLUMN k bigint;对应的测试结果如下:

- 随着背景流量并发量的攀升,使用 gh-ost 工具的变更耗时显著增长,且当并发量达到 50 时,其增量回放已经没办法追上流量的修改,无法顺利完成变更;
- 即便在面临 50 并发的背景流量,pt-osc 工具依旧能够保证变更任务成功完成,但是变更时间会有所增加;
- PolarDB-X 对分区表
执行无锁列类型变更操作时,展现出了较高的稳定性与效率,其变更时长几乎不受背景流量波动的影响,并且所耗费的时间仅为 pt-osc 工具所需时间的三分之一; - PolarDB-X 对单表执行无锁列类型变更操作时,尽管其变更时长同样会随背景流量并发量的提升而有所增加,但相比与 pt-osc 与 gh-ost,依然展现出的较高的变更效率,耗时大幅缩减;
在变更操作期间,由于涉及一些资源的竞争,sysbench oltp_read_write 工作负载会受到一定的影响,导致 TPS 会有所下滑,具体下降比率详情请参见下表:
| 并发数 | gh-ost | pt-osc | omc 单表 | omc 分区表 |
|---|---|---|---|---|
| 10并发 | 3% | 11% | 15% | 4% |
| 25并发 | 3% | 3% | 7% | 3% |
| 50并发 | 无成绩 | 5% | 11% | 6% |
在单表场景下,尽管 PolarDB-X 的无锁列类型变更相较于 gh-ost 和 pt-osc 工具表现出更快的执行速度,但它对背景流量的暂时性影响要略显显著,这也反映了单个 DN 高并发
而在分区表场景下,PolarDB-X 的无锁列类型变更展现了极佳的性能:不仅变更过程迅速无比,而且其对背景流量的影响控制得与 gh-ost 工具相当,实现了速度与稳定性兼顾的优越成效。




