Mixed format + DML limit 引发的血案

简介:

背景

  1. MySQL版本 5.6.16
  2. DB架构(级联复制) M --> New_M(log_slave_update)--> S
  3. 相信做DB拆分,机房搬迁,数据库升级,都会用到这种类似的架构吧。
  4. 那么问题来了,最近做数据校验的时候,发现New_S 的数据竟然比 M,New_M 还多,是否奇怪?

m_s_s

案例&分析

  1. 如何做数据校验? pt-table-checksum ,或自己写对比程序。
  2. 校验出来后,发现A表在M,S,New_M三个实例上 有300条记录, New_S,Bak_etl 却有500条记录

m_s_s_2

为什么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

m_s_s_3

New_M的binlog

m_s_s_4

很明显,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

m_s_s_7

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

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 模式

m_s_s_5

ROW 模式

m_s_s_6

总结

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

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

目录
相关文章
|
7月前
|
存储 SQL 关系型数据库
【MySQL异常】Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNA
【MySQL异常】Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNA
63 0
|
7月前
|
SQL Oracle 关系型数据库
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
74 0
|
11天前
|
SQL 关系型数据库 MySQL
MySQL SQL error: #1271 - Illegal mix of collations for operation ‘UNION‘
MySQL SQL error: #1271 - Illegal mix of collations for operation ‘UNION‘
|
6月前
|
数据库
解决which is not functionally dependent on columns in GROUP BY clause;...sql_mode=only_full_group_by
解决which is not functionally dependent on columns in GROUP BY clause;...sql_mode=only_full_group_by
44 0
|
8月前
|
SQL 关系型数据库 MySQL
mysql查询出现QSqlQuery::value: not positioned on a valid record
mysql查询出现QSqlQuery::value: not positioned on a valid record
126 0
|
SQL 关系型数据库 MySQL
postgre分页查询报错:ERROR: LIMIT #,# syntax is not supported 建议:Use separate LIMIT and OFFSET clauses
postgre分页查询报错:ERROR: LIMIT #,# syntax is not supported 建议:Use separate LIMIT and OFFSET clauses
240 0
postgre分页查询报错:ERROR: LIMIT #,# syntax is not supported 建议:Use separate LIMIT and OFFSET clauses
解决sql update 1292 - Truncated incorrect DOUBLE value:
出现这种错误,我属实焦头烂额了一会儿,这个错误基本可以分为以下两种情况: 一:你的字段类型是varchar,但是你这样进行操作,是不对的, UPDATE StuCose SET Cno=60 应该是: UPDATE StuCose SET Cno='60' 二:你更新操作进行子查询时,需要的两个表的相同的字段的类型不同,比如你的cose表中的Cno是int类型, 但是你的stucose表中是varchar类型 ,这个时候类似这样进行了子查询的update就会报错 UPDA.
416 0
解决sql update 1292 - Truncated incorrect DOUBLE value:
|
SQL Java 数据库连接
JPA异常:Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
JPA异常:Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
1763 0
Unsafe query: ‘Update‘ statement without ‘where‘ updates all table rows at once
Unsafe query: ‘Update‘ statement without ‘where‘ updates all table rows at once
611 0