【20180507】MySQL主从在线修改从库binlog格式从STATEMENT更改成ROW格式

需求

公司内部有几十套基于传统复制的MySQL主从实例,而且binlog的格式都是STATEMENT格式。在接手这些MySQL主从实例之后就有考虑过想将binlog格式更改成ROW格式。而这次则是因为我们elk上面一个第三方工具需要解析和监听binlog信息,并且只能解析ROW格式的binlog,借此机会正好将公司部分MySQL主从复制实例的binlog格式更改成ROW格式。

ROW和STATEMENT比对

  1. row格式
    • 优点:就是能够完全保证主从数据的一致性,不会出现因为在SQL中使用MySQL自带的函数导致数据不一致的现象。例如:当使用now()函数的时候,可能因为从库延时的问题导致时间的数据不一致。线上是有遇到过这个问题的。
    • 缺点:就是会消耗比较大的磁盘空间和磁盘IO;还有一个比较重要的问题就是因为ROW格式是基于每行进行修改的,若是在master执行一个update修改5000行数据,那么slave就会执行5000次修改数据操作,那么这就会带来更严重的主从延迟。(因为我们线上使用的是MySQL5.6,是基于schema的并行复制,并且slave的硬件资源是比master差的)
  2. statement格式
    • 优点:就是消耗较少的磁盘存储和IO。
    • 缺点:可能会导致数据不一致,并且在做基于binlog恢复的时候可能会出现数据不一致的现象。

binlog格式变更的难点

虽然binlog变更是可以进行在线修改的,但是由于MySQL的master上面存在许多的长链接,哪怕你动态修改之后,长链接的写入和修改还是旧的binlog格式。在这里最开始有提出过俩个方案:

  • 重启master。但是线上业务无法中断,所以无法进行修改。
  • kill掉所有的长链接。但是由于长链接太多,一个个去kill掉的话实在是耗费时间和经历,所以也不被认可。

解决方案

最后还是回归到需求本身,关于我们的需求就是需要解析binlog的格式是ROW格式,所以我们最后的方案就是在slave上面修改binlog的格式为ROW格式。(log_slave_updates参数必须在slave上面打开。否则master通过binlog传递到slave上面重放的SQL是不会在slave本地的binlog记录的)

  • 但是需要注意的是修改完毕之后要想在slave上面的需要重启启动复制。即stop slave,start slave。否则是不会生效的。
  • 还有一个需要注意的是,当slave上面已经修改成了ROW格式的时候,这个时候在将slave的binlog格式修改成STATEMENT格式的话,复制是会报错的,哪怕重新restart slave 也会报错。

猜你喜欢

转载自blog.51cto.com/11819159/2113690