天天看点

Mixed format + DML limit 引发的血案

mysql版本 5.6.16 db架构(级联复制) m --> new_m(log_slave_update)--> s 相信做db拆分,机房搬迁,数据库升级,都会用到这种类似的架构吧。 那么问题来了,最近做数据校验的时候,发现new_s 的数据竟然比 m,new_m 还多,是否奇怪?
Mixed format + DML limit 引发的血案
如何做数据校验? pt-table-checksum ,或自己写对比程序。 校验出来后,发现a表在m,s,new_m三个实例上 有300条记录, new_s,bak_etl 却有500条记录
Mixed format + DML limit 引发的血案

为什么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条记录了。

接下来,我们验证下

Mixed format + DML limit 引发的血案
Mixed format + DML limit 引发的血案

很明显,new_m 相比 m,少了很多binlog event,有部分binlog(从214568151开始,全部丢失)都没了。

ok,问题确认了,但是由于sql语句已经被强制转换成了row模式的关系,sql语句如何定位呢?

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

performance_schema> select * from events_statements_summary_by_digest where digest_text like '%broker_user_relation_sub%'g

Mixed format + DML limit 引发的血案

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

1) 为什么binlog会丢失? 2) 什么情况下会丢失?

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

为什么binlog会丢失?

条件1:当binlog format 设置为mixed时,普通复制不会有问题,但是级联复制在特殊情况下会binlog丢失。 条件2:当出现大量数据(400w左右)扫描的更新,删除,插入的时候,且有不确定dml语句(如:delete from table where data<'n' limit )的时候. 当条件1 和 条件2 同时满足时,会导致问题的发生。以上案例,就是证据。

接下来,我们再来测试下我们的理论。这次我们不用delete + limit,用 insert into select

Mixed format + DML limit 引发的血案
Mixed format + DML limit 引发的血案

强烈建议mysql binlog format 设置成row模式来确保主从数据的一致性。

set global binlog_format=row; 禁止非确定性因素的dml,尤其是dml + limit 且没有order by的情况。