MySQL DDL–ghost工具学习

GHOST工作流程图:

GHOST工作原理:

  1. 、首先新建一张ghost表,结构与源表相同
  2. 、使用alter命令修改ghost
  3. 3.1、模拟从库命令获取主库上该表的binlog(基于全镜像的行模式的binlog包含更改前和更改后的所有数据),并解析成语句到ghost表上执行。
  4. 3.2、获取源表的数据范围(如按照主键获取到最大值和最小值),然后将数据拆分为多个批次拷贝插入到ghost表
  5. 、锁住源表,防止用户修改源表数据
  6. 、将源表重命名,将ghost表改名为源表
  7. 、释放表锁,清理gh-ost工具产生的表。

GHOST有工作模式:

  1. .连接主库直接修改
  2. 直连主库
  3. 主库上创建ghost表
  4. 新表(ghost表)上直接alter修改表结构
  5. 迁移原表数据到新表
  6. 拉取解析binlog事件,应用到新表
  7. -over阶段,用新表替换掉原表
  8. .连接从库间接应用到主库
  9. 连接从库
  10. 校验完后,在主库创建新表
  11. 迁移原表数据到新表
  12. 模拟从库的从库,拉取解析增量binlog应用到主库
  13. -over阶段,用新表替换掉原表
  14. 两者不同的点就在于,通过连接从库来进行变更,对主库的性能影响最小,但使用主库能够减少网络影响,操作速度更快。

如何保证源表和新表数据一致:

  1. 由于使用binlog获得的数据总是新于或者等于从源表拷贝的数据:
  2. 、在应用binlog导出的数据时,将UPDATE和DELETE直接应用ghost表,将INSERT修改为REPLACE INTO再应用到ghost表。
  3. 、在copy源表数据到ghost表时,使用INSERT IGNORE来忽略掉ghost表已存在的记录
  4. 、对于在gh-ost工作期间发生的DELETE操作:
  5. :如果记录在从源表删除前被复制到ghost表,则ghost表中记录会在应用binlog导出的DELETE命令时删除。
  6. :使用记录在从源表复制到ghost表之前被删除,则记录不会被复制到ghost表,应用binlog导出的DELETE命令也不会报错。

GHOST支持跨服务器操作

  1. 假设有一套主从复制A1-->A2,A1为主库,A2为从库,另有一台服务器B1装有gh-ost,可以在B1上执行对A1上表的修改:
  2. 、对于数据拷贝操作,B1发送查询到A1上先获取最大值和最小值,然后在B1上进行拆分成不同批次,再从B1上发送命令给A1执行小范围数据拷贝
  3. 、对于Binlog解析,先模拟B1到A1的搭建复制,从A1上拉取binlog到B1,在B1上解析成SQL命令,再发送到A1上执行。
  4. 对于跨服务器执行gh-ost命令,会导致大量数据在数据库服务器到命令服务器之间传输,需要考虑网络带宽和网络稳定

重命名原理

  1. 在pt-osc或者online ddl中,最后的rename操作一般是耗时比较短,但如果表结构变更过程中,有大查询进来,那么在rename操作的时候,会触发MDL锁的等待,如果在高峰期,这就是个严重的问题。所以gh-ost是怎么做的呢?
  2. gh-ost利用了MySQL的一个特性,就是原子性的rename请求,在所有被blocked的请求中,优先级永远是最高的。gh-ost基于此设计了该方案:一个连接对原表加锁,另启一个连接尝试rename操作,此时会被阻塞住,当释放lock的时候,rename会首先被执行,其他被阻塞的请求会继续应用到新表。

唯一索引问题

  • 如果通过gh-ost来新增唯一索引,由于REPLACE INTO和INSERT IGNORE会受到ghost表上唯一索引的影响,当在唯一索引上存在数据重复时,会导致数据丢失。