Mysql Online DDL 和 pt-ost 、gh-ost 简要

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql Online DDL 和 pt-ost 、gh-ost 简要相关的知识,希望对你有一定的参考价值。

参考技术A mysql 5.6 之前版本中 , 如果要修改一个表的ddl信息 ,需要锁表 。

具体步骤如下:

下面是Mysql官方文档对于DDL操作的总结:

http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html

http://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.html

可以使用 Alter 语句支持 DDL 特性 ,比如可以用 LOCK = NONE 无锁变更。

percona是一个开源产品 , 是管理Mysql的工具。

PT-OSC(Percona Toolkit Online Schema Change)

https://www.percona.com/doc/percona-toolkit/3.0/pt-online-schema-change.html

Percona Toolkit 包含很多 mysql 管理的功能 ,现在要说的是 online-schema-change上

PT-OSC 原理是建表 ,使用触发器同步数据 ,然后原子性rename。

这样可以支持在线无锁,不停机Online-DDL 。

具体步骤如下:

Percona 有一些限制和缺陷 ,根据它的原理 ,原表不能存在触发器 ,这玩意是唯一。另外原表必须存在PK或者UK。另外就是触发器的问题了,触发器带来性能开销,并且无法停止,那我就不能控制我同步的开关和速度。

但是gh-ost说它可以。

https://github.com/github/gh-ost

go-ost基于bin-log同步 , 基于binlog肯定都是伪装成一个replica。

由于使用单线程回放binlog来替换触发器,所以增量DML回放效率不如触发器,因为pt-osc的增量回放并发度是与业务DML并发度相同的,是多线程的。

相对于percona的优势是:

因为出的太晚了 ,然后percona 和 gh-ost等等开源产品已经大规模实践了,Mysql就更加没什么实践案例和经验了,大家就不太愿意尝试或者迁移了。

大厂来说基本上都是平台封装了,类似idb ,会把无锁变更细节屏蔽了,只需要提工单就可以了 ,但是底层基本上也是建表同步rename个思路。

小公司的话,可以使用percona 、 go-ost 等工具。

MySQL 8.0 Online DDL和pt-osc、gh-ost深度对比分析

Mysql Online DDL

pt-online-schema-change

gh-ost

MySQL5.6在线表结构变更(online ddl)总结

MySQL5.6 Online DDL

MySQL5.6 Online DDL

简单介绍

ddl包含了copy和inplace方式,对于不支持online的ddl操作采用copy方式。对于copy方式,copy过程中全程锁表,不允许写(rename阶段会禁止读写),比如修改表字段的类型,包括修改长度,对于inplace方式,mysql内部以是否修改记录格式为基准也分为两类,一类需要重建表(重新组织记录,重建过程中会建立临时ibd文件),比如添加索引、添加/删除列、修改列NULL/NOT NULL属性等;另外一类是只需要修改表的元数据,比如删除索引、修改列名、修改列默认值、修改列自增值等。MySQL将这两类方式分别称为rebuild方式和no-rebuild方式。

online ddl主要包括3个阶段,prepare阶段,ddl执行阶段,commit阶段,rebuild方式比no-rebuild方式实质多了一个ddl执行阶段,prepare阶段和commit阶段类似。

prepare阶段
  1. 创建新的临时frm文件(MySQL server层建的)
  2. 升级MDL_SHARED_UPGRADABLE到EXCLUSIVE-MDL锁,禁止读写
  3. 根据alter类型,确定执行方式(copy,online-rebuild,online-norebuild)
  4. 更新数据字典的内存对象
  5. 分配row_log对象记录增量
  6. 生成新的临时ibd文件

此阶段主要是innodb引擎做一些校验,分配空间,初始化等操作,时间不长,对于用户感觉不出来禁止读写

ddl执行阶段
  1. 降级EXCLUSIVE-MDL锁到MDL_SHARED_UPGRADABLE,允许读写
  2. 扫描old_table的聚集索引每一条记录rec
  3. 遍历新表的聚集索引和二级索引,逐一处理
  4. 根据rec构造对应的索引项
  5. 将构造索引项插入sort_buffer块
  6. 将sort_buffer块插入新的索引
  7. 处理ddl执行过程中产生的增量(仅rebuild类型需要)
commit阶段
  1. 升级MDL_SHARED_UPGRADABLE到EXCLUSIVE-MDL锁,禁止读写
  2. 重做最后row_log中最后一部分增量
  3. 更新innodb的数据字典表
  4. 提交事务(刷事务的redo日志)
  5. 修改统计信息
  6. rename临时idb文件,frm文件
  7. 变更完成

对于norebuid模式(如删除索引),InnoDB二级索引只需要更新内部视图,并标记这个索引的空间可用,去掉数据库元数据上该索引的定义即可,都是在原表上操作,不需要重建与copy数据,所以速度非常快,基本可以忽略阻塞读写的时间

row_log说明
  1. Row Log中记录的是Online创建索引期间,原表上的DML操作这些操作包括:ROW_OP_INSERT;ROW_OP_DELETE_MARK等
  2. Row Log以Block的方式存储,若DML较多,那么Row Logs可能会占用多个Blocks。row_log_t结构中包含两个指针:head与tail,head指针用于读取Row Log,tail指针用于追加写新的Row Log
  3. 在重用Row Log时,算法遵循一个原则:尽量减少索引树加锁的时间(索引树加X锁,也意味着表上禁止了新的DML操作)
索引树加锁的场景
  1. 在重用Row Log跨越新的Block时,需要短暂加锁;
  2. 若应用的Row Log Block是最后一个Block,那么一直加锁应用最后一个Block,由于禁止了新的DML操作,因此此 Block应用完毕,新索引记录与聚簇索引达到一致状态,重用阶段结束;
  3. 在应用中间Row Log Block上的row log时,无需加锁,新的DML操作仍旧可以进行,产生的row log记录到最后一个Row Log Block之上;
源码分析

虽然画了上面的图,但是里面的细节还是有很多的不懂,不明白,还是只能知道大概的流程,对于每一个点都是一个很深的知识点,commit阶段也还没有整理,待补

以上是关于Mysql Online DDL 和 pt-ost 、gh-ost 简要的主要内容,如果未能解决你的问题,请参考以下文章

MySQL Online DDL详解

MySQL5.6 Online DDL

MySQL--Online DDL

mysql5.7 online ddl怎么查看进度

关于MySQL Online DDL

mysql 5.6 online ddl