Mysql 官方DDL
Mysql 5.6 之前版本ddl实现方式
在 Mysql 5.6 之前版本中 , 如果要修改一个表的ddl信息 ,需要锁表 。
具体步骤如下:
根据原表语句创建临时表
对原表加写锁
修改临时表
从原表copy数据到临时表
释放原表写锁
原子语句rename表名 ,原表被删除 ,临时表成为生产表
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 无锁变更。
Online DDL的开源工具
Percona
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 。
具体步骤如下:
根据原表语句创建新表
Alter 语句更改新表
在原表创建触发器 ,包含INSERT 、 UPDATE 、DELETE。
从原表拷贝数据到新表 ,同时通过触发器将原标写操作映射到新表。
如果原表有外键 ,处理外键
原子rename两张表 (now -> old , new -> now )
删除改名后的old原表。
Percona 有一些限制和缺陷 ,根据它的原理 ,原表不能存在触发器 ,这玩意是唯一。另外原表必须存在PK或者UK。另外就是触发器的问题了,触发器带来性能开销,并且无法停止,那我就不能控制我同步的开关和速度。
但是gh-ost说它可以。
go-ost
GitHub's online schema migration for MySQL
https://github.com/github/gh-ost
先连接到主库上,根据alter语句创建所需的新表;
作为一个“备库”连接到其中一个真正的备库上,一边在主库上拷贝已有的数据到新表,一边从备库上拉取增量数据的binlog;
然后不断的把 binlog 应用回主库;
cut-over是最后一步,锁住主库的源表,等待binlog 应用完毕,然后替换gh-ost表为源表。
go-ost基于bin-log同步 , 基于binlog肯定都是伪装成一个replica。
由于使用单线程回放binlog来替换触发器,所以增量DML回放效率不如触发器,因为pt-osc的增量回放并发度是与业务DML并发度相同的,是多线程的。
相对于percona的优势是:
对于DDL操作的灵活度掌控,可暂停,可动态修改参数;DBA可以根据执行情况来快速调整预设的参数,可快可慢,实现DDL操作性能和对业务影响的平衡;
更为稳健的切表控制:将-cut-over-lock-timeout-seconds和-default-retries 配合使用,可以对切表进行灵活的控制。避免pt-osc切表异常导致对业务造成严重影响;
官方Online-DDL为什么不火?
因为出的太晚了 ,然后percona 和 gh-ost等等开源产品已经大规模实践了,Mysql就更加没什么实践案例和经验了,大家就不太愿意尝试或者迁移了。
工作中的DDL
大厂来说基本上都是平台封装了,类似idb ,会把无锁变更细节屏蔽了,只需要提工单就可以了 ,但是底层基本上也是建表同步rename个思路。
小公司的话,可以使用percona 、 go-ost 等工具。