gh-ost工具
背景
Percona社区的pt-osc的开源DDL工具依赖于触发器来将源表的写操作映射到新表。虽然使用触发器可以提高同步的效率,但触发器执行的开销会对于主库的性能产生很大的影响。另外拷贝数据和变更数据可能处于并行状态,如果在迁移过程中对表的更新比较频繁会引入大量的锁竞争问题。
gh-ost是GitHub开源的一款在线DDL工具,相比pt-osc不依赖于触发器,而是通过模拟从库,在格式为ROW的Binlog中获取增量的变更,再异步同步到镜像表中。其将迁移的写入负载与主服务器的工作负载分离,避免了对于主库性能的影响。同时异步执行增量变更也规避了触发器导致的锁竞争问题。此外gh-ost维护了一张心跳表,用来记录DDL过程中的每个阶段,在出现异常时,可以从根据心跳日志恢复到指定位置,解决了pt-osc在运行过程中出现异常,需要从头开始的局限。
流程图
gh-ost三种模式架构
- 连接从库,在主库转换(默认)
- 在主库创建和原表结构相同的_xxx_gho表,和变更记录日志文件_xxx_ghc表,用来写入Online-DDL的进度以及时间。
- 修改_xxx_gho表的结构。
- 在主库上拷贝已有的数据到_xxx_gho。
- 从备库上获取增量Binlog,完成增量数据的变更。
- 在源表上加锁,确认_xxx_ghc表中的时间,保证数据同步。
- 用_xxx_gho替换源表。
- 连接主库,在主库转换
- 在主库创建_xxx_gho表和_xxx_ghc表。
- 修改_xxx_gho表的结构。
- 在主库上拷贝源表的数据已有的数据到_xxx_gho。
- 在主库上获取增量Binlog,完成增量数据的变更。
- 在源表上加锁,确认_xxx_ghc表中的时间,保证数据同步。
- 用_xxx_gho表替换源表。
- 在从库上测试和转换
该模式下gh-ost会简单连接到主库,但是所有的操作都是在从库上进行,不会对主库进行任何改动。
“-migrate-on-replica”选项让 gh-ost 直接在从库上修改表。最终的切换过程也是在从库正常复制的状态下完成的。
“-test-on-replica”表明操作只是为了测试目的。在进行最终的切换操作之前,复制会被停止。原始表和临时表会相互切换,再切换回来,最终相当于原始表没变动。主从复制暂停的状态下,可以检查和对比这两张表中的数据。
常用参数
关于gh-ost工具的参数配置项说明参考官方文档。
使用限制
- Binlog格式必须使用row,且“binlog_row_image”的值必须是“FULL”。
- 需要用户的权限为:SUPER, REPLICATION CLIENT, REPLICATION SLAVE on *.* and ALL on dbname.*
- 如果确认Binlog的格式为row,那么可以加上“-assume-rbr”,则不再需要super权限。
- 不支持带有外键约束的表。
- 不支持带有触发器的表。
- 执行DDL前后的表,需要有相同的主键或者有非空的唯一索引。
- 迁移表的主键或者非空唯一索引包含枚举类型时,迁移效率会大幅度降低。
参考案例
gh-ost -max-load=Threads_running=20 \ -critical-load=Threads_running=100 \ -chunk-size=2000 -user="temp" -password="test" -host=**.*.*.* \ -allow-on-master -database="sbtest" -table="sbtest1" \ -alter="engine=innodb" -cut-over=default \ -exact-rowcount -concurrent-rowcount -default-retries=120 \ -timestamp-old-table -assume-rbr -panic-flag-file=/tmp/ghost.panic.flag \ -execute