OnlineSchemaChange是Facebook开源的在线修改表结构的工具,具体原理这里不多说了,有兴趣的同学可以看下官方文档:https://github.com/facebookincubator/OnlineSchemaChange/wiki

这里主要介绍下在迁移的时候使用的情况,首先官网的OSC工具不支持主从同步,当时测试是在单库上进行测试,而生产环境是有主从的,结果在主库上直接运行了OSC,可以看到如下的输出:

wKioL1meQPOhsJAqAAGVGMl6L2E154.png-wh_50

可以看到主库运行基本正常,表结构也正常修改了,并没有锁表影响到线上正常业务

wKiom1meQP_z2rlhAAFn9NXYzOE021.png-wh_50

发现主从不一致后的排查:

查看binlog事件,看具体是哪个事务导致的主从不一致

wKioL1meQPXQpJx9AADVi-YrJ5w970.png-wh_50

wKiom1meQQCQ0opqAAELNZmIBiE751.png-wh_50

对binlog同步出错的事务sql进行反复的查看及核对

wKioL1meQPWiNBYOAAEvFrHl9u0352.png-wh_50

wKiom1meQQLBwX22AAAuGG__4k0644.png-wh_50

根据从库的状态可以判断出是__osc_chg_orders是这个临时表不存在导致无法同步

wKioL1meQPfTd2qfAADA48EmyAk899.png-wh_50

随后找到网上说跳过错误事务就可以恢复同步,进行了

slave stop; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; slave start; show slave status\G

进行跳过一个错误事务后再次查看,发现每次都卡在没有这个__osc_chg_orders临时表

wKioL1meQPfDY5nlAADQ0y2Dz1U042.png-wh_50


网上查询到可以忽略某些表的同步,在从库上可以忽略某些表的同步,在主库binlog中有大量的临时表事务,开始我们手动一条一条的跳过,发现并不可行,手动执行50次后发现__osc_chg_orders临时表的数据可能跟原表的数据量一样大,也就是1千万条,这样我们难道要跳过1千万个事务,如果直接跳过1kw也事务,也不行,因为这里面还有在上线正常执行的事务,这里发现可以忽略这个表同步,在从库中设置忽略就是会跳过binlog中关于__osc_chg_orders临时表的事务,但是binlog还会记录,如果在主库中忽略就是直接不记录binlog,从库自然就无法同步到,这里采用从库忽略binlog中这个__osc_chg_orders临时表,修改配置文件:

wKiom1meQQKRWn6WAAANtDZufE8358.png-wh_50


忽略后发现可以跳过所有__osc_chg_orders临时表相关的错误事务,但是还会出现错误代码1032的事务,随后按照这种思路进行查找,自己遇到的问题别人可能事先都已经遇到了,查找后发现有忽略错误代码的配置:

忽略后出现1032的报错,在修改忽略1032的报错,问题解决,同步正常

wKiom1meQQOz8xREAAAMw81klLg477.png-wh_50


参考跳过错误代码:

wKioL1meQPjx3Ib1AAD4CMwXrgM853.png-wh_50

最后只能手动修改从库的表结构,主从同步恢复正常,至此问题解决,然后对照主库的binlog事务在从库中进行查询,正常的insert binlog事务,在从库中可以查询到,说明binlog中的正常事务是被同步正常,只是跳过了错误事务,保证了主从之间的数据一致性


从库修改简单总结如下:

1、采用跳过单个事务的办法,发现错误事务太多,中间又混杂着正确的事务,导致无法一次性跳过所有的错误事务


2、采用忽略特性错误事务的同步,发现所有有问题事物都是因为同步一张临时表而导致的,只需要跳过这个临时表,这样就能跳过大部分的错误事务,正常执行的事务也不会被影响,同样会被同步


3、采用忽略同步错误代码来实现,直接跳过同错误代码的事务,恢复同步


4、比对主库binlog中正常事务是否在从库执行,查询在主库binlog中的正常insert事务,在从库中进行select对应插入数据,可以查询到,说明其中的正常事务通过binlog同步到从库成功,至此解决了主从不同步的问题!



--------------------- osc bug解决 ----------------------------------------


这里要注意一点就是binlog要使用ROW模式


1.解决了不支持ip+port的模式,官网只支持socket的方式,也就是只能在本地数据库运行,但目前大多都是云数据库,所以只有socket连接方式不能满足目前的需求,修改源码后支持了host+port的方式


2.解决主从不一致的问题,官网只支持单库的情况,也就是主从的情况只会修改主库的表结构,并不会修改从库的表结构,原因是在每次修改前OSC都会将数据库的binlog关闭,导致生成的临时表无法通过binlog同步到从库,修改源码让其不关闭binlog,解决了主从不同步的问题


PS:官网这么做可能考虑到写binlog性能会下降,的确如此,但是对于目前云库的性能来说基本没有影响,可以正常的修改表结构,测试1千万的表修改表结构也就10分钟左右,效率很高,而且不会影响线上业务的持续运行



官方GitHub OSC:https://github.com/facebookincubator/OnlineSchemaChange

改良后的git地址: https://github.com/lxshopping/OnlineSchemaChange