GitHub正式宣布以开源的方式发布gh-ost:GitHub的MySQL无触发器在线更改表定义工具!
gh-ost是GitHub最近几个月开发出来的,目的是解决一个经常碰到的问题:不断变化的产品需求会不断要求更改MySQL表结构。gh-ost通过一种影响小、可控制、可审计、操作简单的方案来改变线上表结构。
在介绍gh-ost之前,我们先了解一下各种现有方案,以及为什么要自己开发一个新工具。
已有的在线修改表定义方案
目前,在线修改表定义的任务主要是通过这三种途径完成的:
还有其它的比如Galera Cluster的Rolling Schema Upgrade,或者非InnoDB引擎的表等。GitHub的MySQL数据库用的都是主从复制架构,使用可靠的InnoDB引擎。
为什么我们决定去设计一个新解决方案,而不是直接从上面的几种方案中选一个用?现有的解决方案都有着自身的局限性,下面就对它们的不足之处做个简单分析。我们会主要深入地分析基于触发器的在线修改表定义工具的不足之处。
基于触发器的解决方案有什么不好?
所有在线修改表定义的工具运行原理都是相似的:创建一张与原始表定义相同的临时表,趁上面没有数据时先改好表定义,然后慢慢地、用增量方式把数据从原始表拷到临时表,同时不断的把进行中的原始表上的数据操作(所有应用在原始表上的插入、删除、更新操作)也应用过来。当工具把所有数据都拷贝完毕,两边数据同步了之后,它就用这张临时表来替代原始表。修改过程就结束了。
像pt-online-schema-change、LHM和oak-online-alter-table这些工具用的都是同步复制的方式,对表的每一条数据修改都会立刻在同一个事务里就应用到临时表上。Facebook的工具用的则是异步模式,先把修改操作都记在一张修改日志表里,然后再取出来执行,把修改操作应用到临时表上。这些工具全都使用触发器来提取那些应用在目标表上的操作。
触发器都是存储过程,在表上有插入、删除、修改操作时就会被触发。触发器可能包括好多条语句,这些语句都是和引发触发器的那条操作在相同的事务空间内运行的,因此保证了这些操作的原子性。
一般意义上的触发器,尤其是基于触发器的表定义修改操作,都有如下问题:
gh-ost
gh-ost是gitHub’s Online Schema Transmogrifier/Transfigurator/Transformer/Thingy的缩写,意思是GitHub的在线表定义转换器。
gh-ost有以下特点:
无触发器
gh-ost不使用触发器,它跟踪二进制日志文件,在对原始表的修改提交之后,用异步方式把这修改内容应用到临时表中去。
gh-ost希望二进制文件使用基于行的日志格式,但这并不表示如果主库上使用的是基于语句的日志格式,就不能用它来在线修改表定义了。事实上,我们常用的方式是用一个从库把日志的语句模式转成行模式,再从这个从库上去读日志。搭一个这样的从库并不复杂。
轻量级
因为不需要使用触发器,gh-ost把修改表定义的负载和正常的业务负载解耦开了。它不需要考虑被修改的表上的并发操作和竞争等,这些在二进制日志中都被序列化了,gh-ost只操作临时表,完全与原始表不相干。事实上,gh-ost也把行拷贝的写操作与二进制日志的写操作序列化了,这样,对主库来说只是有一条连接在顺序的向临时表中不断写入数据,这样的行为与常见的ETL相当不同。
可暂停
因为所有写操作都是gh-ost生成的,而读取二进制文件本身就是一个异步操作,所以在暂停时,gh-ost是完全可以把所有对主库的写操作全都暂停的。暂停就意味着对主库没有写入和更新。不过gh-ost也有一张内部状态跟踪表,即使在暂停状态下也会向那张表中不断写入心跳信息,写入量可以忽略不计。
gh-ost提供了比简单的暂停更多的功能,除了暂停之外还可以做:
上述所有指标即使在修改表定义的过程中也可以动态修改。
动态可控
如果别的工具在修改过程中产生了比较高的负载,DBA只好把它停掉再修改配置,比如把一次拷贝的数据量改小些,然后再从头开始修改过程。这样的反复操作代价非常大。
gh-ost通过监听TCP或者unix socket文件来获取命令。即使有正在进行中的修改工作,用户也可以向gh-ost发出命令修改配置,比如可以这样做:
可审计
用上面所说的相同接口也可以查看gh-ost的状态,查看当前任务进度、主要配置参数、相关MySQL实例的情况等。这些信息通过网络发送命令就可以得到,因此就给了运维人员极大的灵活性,如果是使用别的工具的话一般只能是通过共享屏幕或者不断跟踪日志文件最新内容。
可测试
读取二进制文件内容的操作完全不会增加主库的负载,在从库上做修改表结构的操作也和在主库上做是非常相象的(当然并不完全一样,但主要来说还是差不多的)。
gh-ost自带了--test-on-replica选项来支持测试功能,它允许你在从库上运行起修改表结构操作,在操作结束时会暂停主从复制,让两张表都处于同步、就绪状态,然后切换表、再切换回来。这样就可以让用户从容不迫地对两张表进行检查和对比。
我们在GitHub是这样在生产环境测试gh-ost的:我们有许多个指定的生产从库,在上面不提供服务,只是周而复始地不断地把所有表定义都改来改去。对于我们生产环境地每一张表,小到空表,大到几百GB,都会通过修改存储引擎的方式来进行修改(engine=innodb),这样并不会真正修改表结构。在每一次这样的修改操作最后我们都会停掉主从复制,再把原始表和临时表的全量数据都各做一次校验和,然后比较两个校验和,要求它们是一致的。然后我们恢复主从复制,再继续测试下一张表。我们生产环境的每一张表都这样用gh-ost在从库上做过好多次修改测试。
可靠的
所有上述讲到的和没讲到的内容,都是为了让你对gh-ost的能力建立信任。毕竟,大家在做这件事的时候已经使用类似工具做了好多年,而gh-ost只是一个新工具。
gh-ost工作模式
gh-ost工作时可以连上多个MySQL实例,同时也把自己以从库的方式连上其中一个实例来获取二进制日志事件。根据你的配置、数据库集群架构和你想在哪里执行修改操作,可以有许多种不同的工作模式。
1、连上从库,在主库上修改
这是gh-ost默认的工作模式,它会查看从库情况,找到集群的主库并且连接上去。修改操作的具体步骤是:
如果主库的二进制日志格式是Statement,就可以使用这种模式。但从库就必须配成启用二进制日志(log_bin, log_slave_updates),还要设成Row格式(binlog_format=ROW),实际上gh-ost会在从库上帮你做这些设置。
事实上,即使把从库改成Row格式,这仍然是对主库侵入最少的工作模式。
2、连上主库
如果没有从库,或者不想在从库上操作,那直接用主库也是可以的。gh-ost就会在主库上直接做所有的操作。仍然可以在上面查看主从复制延迟。
3、在从库上修改和测试
这种模式会在从库上做修改。gh-ost仍然会连上主库,但所有操作都是在从库上做的,不会对主库产生任何影响。在操作过程中,gh-ost也会不时地暂停,以便从库的数据可以保持最新。
gh-ost在GitHub的应用
现在GitHub生产环境的表修改操作全都是用gh-ost完成的。每天只要有需求来了,就将它运行起来,有时候一天会做好多次。因为它有审计和控制功能,所以我们还可以把它和我们的Chatops系统整合起来。技术人员可以对它的工作进度有非常清晰的了解,因此可以控制它的行为。在生产环境中各种指标和事件都被收集起来,让大家可以以图形化的方式看到操作情况。
开源
gh-ost按照MIT许可协议向开源社区发布。
尽管现在已经稳定了,但是还是有一些想要继续改进的方面。GitHub现在把它发布出来,希望能得到来自于社区的参与和贡献。他们也会不断把社区提供的建议等公布出来。
[转载]github在线更改mysql表结构工具gh-ost
原文:http://www.cnblogs.com/conanwang/p/5831087.html