更新时间:2024-09-06 GMT+08:00
分享

gh-ost工具

背景

Percona社区的pt-osc的开源DDL工具依赖于触发器来将源表的写操作映射到新表。虽然使用触发器可以提高同步的效率,但触发器执行的开销会对于主库的性能产生很大的影响。另外拷贝数据和变更数据可能处于并行状态,如果在迁移过程中对表的更新比较频繁会引入大量的锁竞争问题。

gh-ost是GitHub开源的一款在线DDL工具,相比pt-osc不依赖于触发器,而是通过模拟从库,在格式为ROW的Binlog中获取增量的变更,再异步同步到镜像表中。其将迁移的写入负载与主服务器的工作负载分离,避免了对于主库性能的影响。同时异步执行增量变更也规避了触发器导致的锁竞争问题。此外gh-ost维护了一张心跳表,用来记录DDL过程中的每个阶段,在出现异常时,可以从根据心跳日志恢复到指定位置,解决了pt-osc在运行过程中出现异常,需要从头开始的局限。

流程图

图1 流程图

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

相关文档