lxgi&

导航

小心,MIXED二进制日志模式可能导致主从数据不一致

之前的文章中,Inside君已经广邀广大MySQL爱好者前来投稿,一旦录取会有象征性的酬谢,共同打造一个良好的MySQL社区氛围。而Inside创建的IMG组织,本周也将在上海正式成立,欢迎各位到时加入IMG,打造最有态度的MySQL组织

 

Inside君发现很多公司的MySQL二进制日志都设置为MIXED,他们认为较之最为安全的ROW格式,MIXED模式日志相对较小,同时也能保证数据同步的可靠性。但是投稿的这位同学,在级联复制模式下,MIXED模式依然会导致数据不一致,真实血淋淋的教训。在和Inside君沟通与测试后,最终定位了该问题。

 

总之,任何情况下,把参数binlog_format设置为ROW吧,具体可以参考Inside君之前发布的MySQL 5.6&5.7最优配置模板

 

背景交代

 

  1. 数据库版本:MySQL社区版 5.6.16

  2. 复制架构:DB架构(级联复制) M -> New_M(log_slave_update)-> S

  3. 相信做DB拆分,机房搬迁,数据库升级,都会用到这种类似的架构

  4. 最近做数据校验的时候,发现New_S 的数据竟然比 M,New_M 还多,是否奇怪?

 



案例与分析

 

数据校验采用工具pt-table-checksum (或自己写对比程序),校验出来后,发现A表在M,S,New_M三个实例上 有300条记录,New_S,Bak_etl 却有500条记录:

 

 

 

为什么New_M的数据比New_S的数据还要少呢???这种情况下,只能比对binlog了,但是binlog数据量如此之大,如何查呢?

 

具体分析下,M,S,New_M的数据是一样的,说明他们之间的复制同步没有问题。New_S和Bak_etl 数据是一样的,说明他们之间执行的binlog也没问题。

 

那么问题就出在M的binlog , New_M的binlog不一致了。换句话说就是:一条DELETE语句,在M上删除了N条,但是在New_M的binlog中只记录了delete N-200。从而导致最后的slave比master要多200条记录了。

 

接下来,就是验证的过程,M上的binlog如下所示:

 

 

而New_M上的binlog为:

 

 

很明显,New_M相比M,少了很多binlog event,有部分binlog(从214568151开始,全部丢失)都没了。OK,问题确认了,但是由于SQL语句已经被强制转换成了ROW模式的关系,SQL语句如何定位呢?

 

还好,这里有5.6新特性Performance schema的帮助,很快定位到了问题SQL:

 

mysql> SELECT * FROM events_statements_summary_by_digest

-> where DIGEST_TEXT LIKE ‘%xxxxx%’\G

 

 

到这个地步,有几个问题:

  1. 为什么binlog会丢失?

  2. 什么情况下会丢失?

 

这几个问题,经过反复测试,得出以下结论:

 

为什么binlog会丢失?

 

条件1:当binlog format 设置为mixed时,普通复制不会有问题,但是级联复制在特殊情况下会binlog丢失。


条件2:当出现大量数据(400W左右)扫描的更新,删除,插入的时候,且有不确定DML语句(如:DELETE FROM table WHERE data<’N’ LIMIT N )的时候,当条件1 和 条件2 同时满足时,会导致问题的发生。以上案例,就是证据。

 

接下来,我们再来测试下我们的理论。这次我们不用DELETE ... LIMIT,用 INSERT INTO ... SELECT ...,最终得到的结果如下所示:

 

 

 

总结

 

强烈建议MySQL的参数binlog_format 设置成ROW模式来确保主从数据的一致性。

 

posted on 2015-12-18 15:01  lxgi&  阅读(1221)  评论(0编辑  收藏  举报