需求
公司内部有几十套基于传统复制的MySQL主从实例,并且binlog的格式都是STATEMENT格式。在接手这些MySQL主从实例以后就有考虑过想将binlog格式更改为ROW格式。而此次则是由于咱们elk上面一个第三方工具须要解析和监听binlog信息,而且只能解析ROW格式的binlog,借此机会正好将公司部分MySQL主从复制实例的binlog格式更改为ROW格式。ide
ROW和STATEMENT比对
- row格式
- 优势:就是可以彻底保证主从数据的一致性,不会出现由于在SQL中使用MySQL自带的函数致使数据不一致的现象。例如:当使用now()函数的时候,可能由于从库延时的问题致使时间的数据不一致。线上是有遇到过这个问题的。
- 缺点:就是会消耗比较大的磁盘空间和磁盘IO;还有一个比较重要的问题就是由于ROW格式是基于每行进行修改的,如果在master执行一个update修改5000行数据,那么slave就会执行5000次修改数据操做,那么这就会带来更严重的主从延迟。(由于咱们线上使用的是MySQL5.6,是基于schema的并行复制,而且slave的硬件资源是比master差的)
- 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 也会报错。