本文共 1843 字,大约阅读时间需要 6 分钟。
GTID 资料
MySQL 5.6 引入了global transaction identifiers (GTIDs,全局事务ID)的特性,这一特性是用来解决主从复制(replication)场景下的一些问题,GTID 只存在于 binlog 中,数据库中是没有的。
要了解 GTID 的话,是一定要看的,另外再推荐推荐三篇 Oracle 同学写的文章(需爬墙):
升级遇到的问题
GTID 能很好的解决 failover 问题,做到主库切换自动化,减轻 DBA 同学的负担,但是这个前提是所有的 MySQL 实例都是 5.6,如果线上实例是 5.5 的,必须全部升到 5.6 才行,而目前官方并没有提供平滑的 5.5 升级到 5.6 GTID 的方式,中间必须要有一个实例重启过程,这是由 GTID 目前的实现方式决定的:
为了描述方便,做如下假设:
迁移步骤如下:
在上面的步骤中,t1 到 t2 的时间段内相当于数据库服务不可用,整个数据库停掉重启,这对线上业务来说是不可接受的,上面是用单个实例A和实例B说明问题,同样可以扩展到集群A和集群B。
gtid_mode 的取值范围除了 OFF 和 ON 这两个值外,还有 UPGRADE_STEP_1和UPGRADE_STEP_2,目前后2者并不支持,不过从名字上看应该是为了升级预留的,但是目前并没有好的升级方式。
解决方案
如果要想做到不重启升级,必须打破之前提到限制条件,booking.com 提供了一种方案,就是打破限制1,创造出一种特殊的模式,使实例处于GTID模式下仍然可以和非GTID的实例进行复制。 详细的方案介绍在这里 ,代码的改动很小,就是让 sql/rpl_slave.cc 中的下面这段检查代码无效:
之前的升级方式是 A->B 这种拓扑,现在变为 A->C->B迁移步骤如下:
这里为了和之前迁移目标一致,多用了一个实例C,其实这时候可以把B给去掉,还是2个实例。可以看到,引入了C后,升级过程中并没有实例重启过程,只有一个短暂的只读时间段,这个是无法避免的,即使不用GTID,也会有这个过程。
目前RDS实例升级到5.6也是用这种方式。如果是集群到集群的话,要注意一点,处于中间状态的实例C最好只有一个,因为这种实例相当于一个GTID转换器,将A中没有 GTID 的 binlog 转成包含 GTID 的 binlog,然后传给B,如果有多个实例C的话,A中同一个binlog 中的事务会转换出不同的GTID,这与 GTID 和事务一一对应的根本原则相矛盾,复制会出问题。当然,如果能保证经过不同的C的binlog事务不会重复的话就可以有多个C。
转载地址:http://missx.baihongyu.com/