转载

GitHub为MySQL社区贡献了新的在线更改表定义工具gh-ost

本月初,GitHub数据库基础架构组的高级软件工程师 Shlomi Noach 在GitHub Engineering网站上发文 宣告 了gh-ost的开源发布。这对MySQL社区是一件大事,宣告停滞许久的MySQL表在线修改表定义操作又有了新的解决方案。

Shlomi这样总结:

gh-ost是GitHub最近几个月开发出来的,目的是解决一个经常碰到的问题:不断变化的产品需求会不断要求更改MySQL表结构。gh-ost通过一种影响小、可控制、可审计、操作简单而且安全的方式来改变线上表结构。

目前,MySQL在线修改表定义的任务主要是通过这三种途径完成的:

  • 在从库上修改表定义,修改之后再提升为新的主库。
  • 通过MySQL 5.6开始提供的InnoDB在线DDL功能。
  • 使用修改表定义工具。现在最流行的是Percona公司的 pt-online-schema-change 和Facebook的 OSC ,也有人使用 LHM 或最早的 oak-online-alter-table 。

在从库上修改表定义的方案耗时长,需要更多的服务器,这种方案需要非常细致的管理工作,并且修改完毕后主从切换过程也会造成短暂的停服。InnoDB在线DDL功能在主库上操作的确是可以满足需求的,但过程不可中断,并且操作完成会造成主从库之间较大的延迟,对许多高可用方案及读写分离等会造成较大困扰。被各大公司DBA广泛接受的作法主要是通过Percona公司的pt-online-schema-change和Facebook的OSC在线操作。

所有在线更改表定义的工具运行原理都是相似的:创建一张与原始表定义相同的临时表,趁上面没有数据时先把临时表改好表定义,然后慢慢地、用增量方式把数据从原始表拷到临时表,同时不断地把进行中的原始表上的数据操作(所有应用在原始表上的插入、删除、更新操作)也应用过来。当工具把所有数据都拷贝完毕,两边数据同步了之后,它就用这张临时表来替代原始表。修改过程就结束了。

像pt-online-schema-change、LHM和oak-online-alter-table这些工具用的都是同步复制的方式,对表的每一条数据修改都会立刻在同一个事务里就应用到临时表上。Facebook的OSC工具用的则是异步模式,先把修改操作都记在一张修改日志表里,然后再取出来执行,把修改操作应用到临时表上。这些工具全都使用触发器来提取那些应用在目标表上的操作。

除了在修改过程中的性能、运维等问题之外,在最后的表切换——用临时表替代原始表——的过程中也非常容易出各种问题:切换失败、丢数据、阻塞原始表业务操作过久等。为此Shlomi曾在博客上基于较优的Facebook OSC的行为连续写了三篇文章( 一 、 二 、 三 )进行分析,进行了细致讨论,并最终给出了一种比较简单而又无损的方案。

GitHub每天数据库基础架构组几乎每天都会收到几次对表结构进行修改的请求,因此各种可能的丢失数据、复杂管理、进度不可见等行为都是不可忍受的。最终他们经过周密的讨论、研发和测试,推出了自己的工具:gh-ost,这个名字是gitHub's Online Schema Transmogrifier/Transfigurator/Transformer/Thingy的缩写,读音同Ghost。

GitHub为MySQL社区贡献了新的在线更改表定义工具gh-ost

gh-ost有以下特点:

  • 无触发器:这也是其他工具最受诟病之处。触发器方案会对MySQL的性能造成比较大的影响,严重时甚至会拖垮主库。
  • 轻量级:gh-ost获取数据表修改操作的方法是伪装成从库连入,获取并解析二进制日志,对临时表插入数据也是增量、可控制的,因此对MySQL主库的性能几乎无影响。
  • 可暂停:当原主库处于业务高峰期时,完全可以暂停gh-ost的操作,暂停就意味着对主库没有写入和更新,这是非常受欢迎的。
  • 动态可控:gh-ost的操作不但可以暂停,还可以动态修改,因此在各种情况下修改了配置之后都不必从头开始重新运行整个修改过程,这是非常节约资源的。
  • 可审计:gh-ost的状态是可以非常容易获取到的,包括当前任务进度、主要配置参数、相关MySQL实例的情况等。gh-ost通过监听TCP或者unix socket文件来获取命令,因此就给了运维人员极大的灵活性。
  • 可测试:gh-ost支持在从库上进行测试,以观察对系统负载的影响、验证正确性等。GitHub生产环境的每一张表都这样用gh-ost在从库上做过好多次修改测试,他们也呼吁大家用这种方式先体验gh-ost的功能,再考虑上线应用。
  • 可靠性高:经过充分的测试之后,现在GitHub生产环境的修改表定义操作已经全部由gh-ost完成了,而且它还有暂停、延迟切换、准确估计任务进度等功能,审计和在线控制功能可以让它轻松地与监控系统结合起来,必然非常受运维人员喜爱。
  • 完美解决切换问题:表切换操作是在线修改表定义的最后一步,其它工具操作到这一步时常常会出现各种问题。Facebook OSC也曾详细分析过这个问题,但它的最终方案是个非原子性切换:先把原始表改名,再把临时表改名顶上。可惜在两次改名中间会有一小段表不存在的时间,在这期间运行的业务语句都会失败,因为目标表不存在。Shlomi等经过严密的论证和实验,给出了 原子性的两阶段切换方案 :用一条连接去持有锁,另一条连接做原子性的rename操作。在rename操作之前,会创建一张 信号表 ,用它来阻塞rename操作,直到所有要求的表切换前提条件就绪。根据这个方案,表切换或者成功,皆大欢喜;或者失败,则对业务无影响,也不会丢失数据,还会释放锁让业务继续,DBA只需要再一次用gh-ost重新尝试切换即可。

gh-ost按照 MIT许可协议 向开源社区 发布 。尽管现在已经稳定了,GitHub仍在计划继续改进它,也非常欢迎来自开源社区的力量来一起试用和提出改进意见。gh-ost是用GO语言实现的。

感谢杜小芳对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们。

原文  http://www.infoq.com/cn/news/2016/08/GitHub-MySQL-gh-ost
正文到此结束
Loading...