MySQL 在线更改 Schema 工具

时间:2017-08-29 18:08:44   收藏:0   阅读:3566

MySQL在线更改schema的工具很多,如Percona的pt-online-schema-change、 Facebook的 OSC 和 LHM 等,但这些都是基于触发器(Trigger)的,今天咱们介绍的 gh-ost 号称是不需要触发器(Triggerless)支持的在线更改表结构的工具。


技术分享


本文先介绍一下当前业界已经存在的这些工具的使用场景和原理,然后再详细介绍 gh-ost 的工作原理和特性。


今天我们开源了GitHub内部使用的一款 不需要触发器支持的 MySQL 在线更改表结构的工具 gh-ost


开发 gh-ost 是为了应付GitHub在生产环境中面临的持续的、不断变化的在线修改表结构的需求。gh-ost 通过提供低影响、可控、可审计和操作友好的解决方案改变了现有的在线迁移表工具的工作模式。


MySQL表迁移及结构更改操作是业界众所周知的问题,2009年以来已经可以通过在线(不停服务)变更的工具来解决。迅速增长,快速迭代的产品往往需要频繁的需改数据库的结构。增加/更改/删除/ 字段和索引等等,这些操作在MySQL中默认都会锁表,影响线上的服务。 向这种数据库结构层面的变更我们每天都会面临多次,当然这种操作不应该影响用户的正常服务。


在开始介绍 gh-ost 工具之前,咱们先来看一下当前现有的这些工具的解决方案。


在线修改表结构,已存在的场景


如今,在线修改表结构可以通过下面的三种方式来完成:



其他的还包括 Galera 集群的Schema滚动更新,以及一些其他的非InnoDB的存储引擎等待,在 GitHub 我们使用通用的 主-从 架构 和 InnoDB 存储引擎。


为什么我们决定开始一个新的解决方案,而不是使用上面的提到的这些呢?现有的每种解决方案都有其局限性,下文会对这些方式的普遍问题简单的说明一下,但会对基于触发器的在线变更工具的问题进行详细说明。



基于触发器的在线修改有哪些问题呢?


所有在线表结构修改工具的操作方式都类似:创建与原表结构一致的临时表,该临时表已经是按要求修改后的表结构了,缓慢增量的从原表中复制数据,同时记录原表的更改(所有的 INSERT, DELETE, UPDATE 操作) 并应用到临时表。当工具确认表数据已经同步完成,它会进行替换工作,将临时表更名为原表。


pt-online-schema-change, LHM 和 oak-online-alter-table 这些工具都使用同步的方式,当原表有变更操作时利用一些事务的间隙时间将这些变化同步到临时表。Facebook 的工具使用异步的方式将变更写入到changelog表中,然后重复的将changelog表的变更应用到临时表。所有的这些工具都使用触发器来识别原表的变更操作。


当表中的每一行数据有 INSERT, DELETE, UPDATE 操作时都会调用存储的触发器。一个触发器可能在一个事务空间中包含一系列查询操作。这样就会造成一个原子操作不单会在原表执行,还会调用相应的触发器执行多个操作。


在基于触发器迁移实践中,遇到了如下的问题:



gh-ost


gh-ost GitHub 的在线 Schema 修改工具,下面工作原理图:


技术分享


gh-ost 具有如下特性:



无触发器


gh-ost 没有使用触发器。它通过分析binlog日志的形式来监听表中的数据变更。因此它的工作模式是异步的,只有当原始表的更改被提交后才会将变更同步到临时表(ghost table)


gh-ost 要求binlog是RBR格式 ( 基于行的复制);然而也不是说你就不能在基于SBR(基于语句的复制)日志格式的主库上执行在线变更操作。实际上是可以的。gh-ost 可以将从库的 SBR日志转换为RBR日志,只需要重新配置就可以了。


轻量级


由于没有使用触发器,因此在操作的过程中对主库的影响是最小的。当然在操作的过程中也不用担心并发和锁的问题。 变更操作都是以流的形式顺序的写到binlog文件中,gh-ost只是读取他们并应用到gh-ost表中。实际上,gh-ost 通过读取binlog的写事件来进行顺序的行复制操作。因此,主库只会有一个单独连接顺序的将数据写入到临时表(ghost table)。这和ETL操作有很大的不同。


可暂停


所有的写操作都是由gh-ost控制的,并且以异步的方式读取binlog,当限速的时候,gh-ost可以暂停向主库写入数据,限速意味着不会在主库进行复制,也不会有行更新。当限速时gh-ost会创建一个内部的跟踪(tracking)表,以最小的系统开销向这个表中写入心跳事件


gh-ost 支持多种方式的限速:



可动态控制


现在的工具,当执行操作的过程中发现负载上升了,DBA不得不终止操作,重新配置参数,如 chunk-size,然后重新执行操作命令,我们发现这种方式效率非常低。


gh-ost 可以通过 unix socket 文件或者TCP端口(可配置)的方式来监听请求,操作者可以在命令运行后更改相应的参数,参考下面的例子:



可审计


同样的,使用上文提到的程序接口可以获取 gh-ost 的状态。gh-ost 可以报告当前的进度,主要参数的配置以及当前服务器的标示等等。这些信息都可以通过网络接口取到,相对于传统的tail日志的方式要灵活很多。


可测试


因为日志文件和主库负载关系不大,因此在从库上执行修改表结构的操作可以更真实的体现出这些操作锁产生的实际影响。(虽然不是十分理想,后续我们会做优化工作)。


gh-ost 內建支持测试功能,通过使用 --test-on-replica 的参数来指定: 它可以在从库上进行变更操作,在操作结束时gh-ost 将会停止复制,交换表,反向交换表,保留2个表并保持同步,停止复制。可以在空闲时候测试和比较两个表的数据情况。


这是我们在GitHub的生产环境中的测试:我们生产环境中有多个从库;部分从库并不是为用户提供服务的,而是用来对所有表运行的连续覆盖迁移测试。我们生产环境中的表,小的可能没有数据,大的会达到数百GB,我们只是做个标记,并不会正在的修改表结构(engine=innodb)。当每一个迁移结束后会停止复制,我们会对原表和临时表的数据进行完整的checksum确保他们的数据一致性。然后我们会恢复复制,再去操作下一张表。我们的生产环境的从库中已经通过 gh-ost 成功的操作了很多表。


值得信赖


上文提到说了这么多,都是为了提高大家对 gh-ost 的信任程度。毕竟在业界它还是一个新手,类似的工具已经存在了很多年了。



gh-ost 操作模式


gh-ost 可以同时连接多个服务器,为了获取二进制的数据流,它会作为一个从库,将数据从一个库复制到另外一个。它有各种不同的操作模式,这取决于你的设置,配置,和要运行迁移环境。


技术分享


a. 连接到从库,在主库做迁移


这是 gh-ost 默认的工作方式。gh-ost 将会检查从库状态,找到集群结构中的主库并连接,接下来进行迁移操作:



如果你的主库的日志格式是 SBR,工具也可以正常工作。但从库必须启用二级制日志(log_bin, log_slave_updates) 并且设置 binlog_format=ROW ( gh-ost 是读取从库的二级制文件)。


如果直接在主库上操作,当然也需要二进制日志格式是RBR。


b. 连接到主库


如果你没有从库,或者不想使用从库,你可以直接在主库上操作。gh-ost 将会直接在主库上进行所有操作。你需要持续关注复制延迟问题。



c. 在从库迁移/测试


该模式会在从库执行迁移操作。gh-ost 会简单的连接到主库,此后所有的操作都在从库执行,不会对主库进行任何的改动。整个操作过程中,gh-ost 将控制速度保证从库可以及时的进行数据同步



gh-ost at GitHub


我们已经在所有线上所有的数据库在线操作中使用了gh-ost ,我们每天都需要使用它,根据数据库修改需求,可能每天要运行多次。凭借其审计和控制功能我们已经将它集成到了ChatOps流程中。我们的工程师可以清醒的了解到迁移操作的进度,而且可以灵活的控制其行为。


开源


gh-ost 在MIT的许可下发布到了开源社区。


虽然gh-ost在使用中很稳定,我们还在不断的完善和改进。我们将其开源也欢迎社会各界的朋友能够参与和贡献。随后我们会发布 贡献和建议的页面。


我们会积极的维护 gh-ost 项目,同时希望广大的用户可以尝试和测试这个工具,我们做了很大努力使之更值得信赖。

来源: https://mp.weixin.qq.com/s?__biz=MzA5ODM5MDU3MA==&mid=2650862287&idx=1&sn=c3453d4e00ea3b70e5688dd66ce91c7c&chksm=8b66158abc119c9c6dc1a04a50f827c4c0c69a01156322838e8aed94078fcff62823a31c1231&scene=35&key=564c3e9811aee0ab643b79f1bf5bfeaa6468d9462d649bee7844775a2fb2d095caeda21fc6aca7ca36121baba0ed3e6f2ca9b6a637fff00f6583ec75d03d528293281d38484f13cc1fb72102953e9224&ascene=7&uin=MTc2Njk5NTA0MQ%3D%3D&devicetype=Windows+10&version=6203005d&pass_ticket=6NpxmVlhP054Xiy7O%2Bh9qQPO8JdLz47GIXcw9kZRoPL%2Fr%2BUx0P5phxefAzy9b8MY&winzoom=1

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!