在腾讯云数据库上使用gh-ost以及几点注意事项

此gh-ost不是本blog用的ghost框架,而是github出的Online DDL工具,目的类似于pt-online-schema-change 和 Facebook的OSC。官方解释是stands for GitHub's Online Schema Transmogrifier/Translator/Transformer/Transfigurator

官方文档https://github.com/github/gh-ost写的够细致了,不想做简单的翻译搬运工,直接还是上手实操。

流程

  • 整体流程分成三个部分:初始化验证、复制、Cut-over
  • 初始化验证
    • 连接replica或者master,并识别master实例标识
    • 初步验证alter修改语句
    • 权限校验、表存在性校验
    • 创建changelog和ghost表
    • 在ghost表上执行alter语句
    • 比较ghost表和原表,确认共通的列、唯一键、验证外键,gh-ost会使用共用的唯一键来分割任务
    • 设置binlog的监听器,并开始监控changelog中的事件变化
    • 将"goodtogo"记录插入到changlog表中,代表迁移准备工作完成
    • 开始通过binlog监控原表的DML操作
    • 读取原表选定的唯一键的min/max值来判断进度
  • 复制
    • 设置心跳(通过频繁写入上个阶段changelog表来判断流程是否顺畅,如果写入减缓就会启动throttling机制减缓迁移进度)并持续更新状态
    • 周期性检查是否需要减速
    • 根据上个阶段选定唯一键拆分迁移任务,分成一块一块的来从原表把数据拷贝至ghost表中
    • 从binglog中读取DML事件,然后按照序列将这些任务排队
    • 整个数据复制和DML任务会穿插进行,通过节流状态暂停
    • 在全部行复制完成后触发"行复制完成"事件
    • 准备进入Cut-over阶段或者延后
  • Cut-over
    • 锁住原表禁止写入,处理还未完成的积压的binlog事件
    • 交换ghost表和原表
    • 清理无用的表

需要满足的条件和限制

  • gh-ost 依赖的唯一键不能有空值,这意味要么为NOT NULL列或者可NULL列但没有任何空值
  • 重命名表名的操作不支持🤣
  • MySQL参数配置
    • binlog_format ROW
    • binlog_row_image FULL
  • gh-ost 账号权限
    • ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE on *.*
    • (或者) SUPER, REPLICATION SLAVE on *.*
    • (或者) REPLICATION CLIENT, REPLICATION SLAVE on *.*

腾讯云MySQL的默认参数binlog_format需要改成ROW,除此之外,腾讯云也没放开SUPER权限,所以我们必须在运行时加入以下参数以避免需要SUPER权限的操作STOP SLAVE/START SLAVE

–allow-on-master # 目前一主多从只能直连master,况且腾讯云也没放开replica访问权
–assume-rbr # 主要是这个可以避免SUPER权限
–assume-master-host # 如果没有放开replica的权限,那么需要指定一下
-aliyun-rds # 原因下述

--aliyun-rds这个参数是因为阿里云隐藏了背后架构,导致@@global.version 和@@global.hostname 取空了,没有通过连接的初始化验证,具体看这个https://github.com/github/gh-ost/issues/470
腾讯云虽然这两个有值了,但是跟实际使用的值差异太大也会导致验证无法通过,可以看一下gh-ost源码发现,它需要查询的值跟gh-ost启动参数值保持一致才能用过
以下源码来源于https://github.com/github/gh-ost/blob/master/go/base/utils.go#L88

省下重新编译和构建,可以直接使用aliyun-rds参数🤣虽然我们是腾讯云🤣

注意事项

  • 不使用trigger方式来迁移数据的原因(pt-osc、facebook osc)
    • trigger在MySQL中是存储过程,执行过程必须中必须要解释执行,对于业务繁忙且量大的表来说可能造成额外的负担
    • trigger方式迁移时在同一个事务中可能会出现死锁的情况
    • 无法中断
    • 无法同时进行多个迁移
    • 没有值得信赖的生产环境的测试。如果replica使用SBR方式复制的话,那么trigger可以允许我们在replica测试,但是如果使用RBR模式的话,我们只能在master进行测试(因为replica依赖trigger触发时的通知,而RBR模式没办法复制这个)
  • 使用gh-ost方案的优缺点
    • 优点:采用异步更新,依赖使用RBR binlog(虽然使用SBR也可以解决);gh-ost倾向使用开启了log-slave-updates的replica来做为自己的复制的源,这样能减少对master的性能影响
    • 缺点:因为采用了异步的方案,其实有很多值得注意的地方
      • 额外增加的流量
      • 代码复杂性