It is everywhere in the world of MySQL that if your replication is broken because an event caused a duplicate key or a row was not found and it cannot be updated or deleted, then you can use ‘STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; ‘ and be done with it. In some cases this is fine and you can repair the offending row or statements later on. But what if the statement is part of a multi-statement transaction? Well, then it becomes more interesting, because skipping the offending statement will cause the whole transaction to be skipped. This is well documented in the manual by the way. So here’s a quick example.

3 rows on the master:

 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
8
9
master> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  1 |   1 |
|  2 |   2 |
|  3 |   3 |
+----+-----+
3 rows in set (0.00 sec)

2 on the slave:

 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
8
slave> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  1 |   1 |
|  3 |   3 |
+----+-----+
2 rows in set (0.00 sec)

Execute a transaction on the master to break replication:

 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
master> BEGIN;
Query OK, 0 rows affected (0.00 sec)
 
master> DELETE FROM t WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
 
master> DELETE FROM t WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
 
master> DELETE FROM t WHERE id = 3;
Query OK, 1 row affected (0.00 sec)
 
master> COMMIT;
Query OK, 0 rows affected (0.01 sec)

Broken slave:

 
 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
slave> show slave status G
*************************** 1. row ***************************
...
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table test.t; Can't find record in 't', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000002, end_log_pos 333
...
1 row in set (0.00 sec)

An attempt to fix replication only caused bigger inconsistencies on slave:

 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
8
9
10
11
slave> STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;
Query OK, 0 rows affected (0.00 sec)
 
slave> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  1 |   1 |
|  3 |   3 |
+----+-----+
2 rows in set (0.00 sec)

This happens because the replication honors transaction boundaries, and is definitely something you should consider the next time you try to use this workaround on a broken slave. Of course, there is pt-table-checksum and pt-table-sync to rescue you when inconsistencies occur, however, prevention is always better than cure. Make sure to put safeguards in place to prevent your slaves from drifting.

Lastly, the example above is for ROW-based replication as my colleague pointed out, but can similarly happen with STATEMENT for example with a duplicate key error.  You can optionally fix the error above by temporarily setting slave_exec_mode to IDEMPOTENT so errors because of missing rows are skipped, but then again, it does not apply in all cases like an UPDATE statement that cannot be applied because the row on the slave is missing.

Here is a demonstration of the problem with STATEMENT-based replication:

 
 
 
 
 
 

Shell

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
master> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  4 |   1 |
|  6 |   3 |
+----+-----+
2 rows in set (0.00 sec)
 
slave> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  4 |   1 |
|  5 |   2 |
|  6 |   3 |
+----+-----+
3 rows in set (0.00 sec)
 
master> BEGIN;
Query OK, 0 rows affected (0.00 sec)
 
master> delete from t where id = 4;
Query OK, 1 row affected (0.00 sec)
 
master> insert into t values (5,2);
Query OK, 1 row affected (0.00 sec)
 
master> delete from t where id = 6;
Query OK, 1 row affected (0.00 sec)
 
master> COMMIT;
Query OK, 0 rows affected (0.15 sec)
 
slave> show slave status G
*************************** 1. row ***************************
...
               Last_SQL_Errno: 1062    
               Last_SQL_Error: Error 'Duplicate entry '5' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'insert into t values (5,2)'
...
1 row in set (0.00 sec)
 
slave> stop slave; set global sql_slave_skip_counter = 1; start slave;
Query OK, 0 rows affected (0.05 sec)
 
slave> select * from t;
+----+-----+
| id | pid |
+----+-----+
|  4 |   1 |
|  5 |   2 |
|  6 |   3 |
+----+-----+
3 rows in set (0.00 sec)

https://www.percona.com/blog/2013/07/23/another-reason-why-sql_slave_skip_counter-is-bad-in-mysql/

Another reason why SQL_SLAVE_SKIP_COUNTER is bad in MySQL的更多相关文章

  1. 查看mysql主从配置的状态及修正 slave不启动问题

    1.查看master的状态 mysql> show master status;  //Position不应该为0 mysql> show processlist;  //state状态应 ...

  2. MySQL Replication 优化和技巧、常见故障解决方法

    MySQL 主从同步错误(error)解决(转) sql_slave_skip_counter参数 附: 一些错误信息的处理,主从服务器上的命令,及状态信息. 在从服务器上使用show slave s ...

  3. mysql主从数据库复制

    http://blog.csdn.net/lgh1117/article/details/8786274 http://blog.csdn.net/libraworm/article/details/ ...

  4. MySQL show slave status命令参数

    ? Slave_IO_State SHOW PROCESSLIST输出的State字段的拷贝.SHOW PROCESSLIST用于从属I/O线程.如果线程正在试图连接到主服务器,正在等待来自主服务器的 ...

  5. canal mysql slave

    [mysqld] log-bin=mysql-bin #添加这一行就ok binlog-format=ROW #选择row模式 server_id=1 #配置mysql replaction需要定义, ...

  6. Mysql主从同步问题汇总

    data-1-1主机是master,data-1-2是slave Last_IO_Errno: 1236 slave查看show slave status\G; 显示Last_IO_Errno: 12 ...

  7. Mysql主从---删除master.info和relya-log.info实验

    relay-log.info, master.info 这连个文件时在建立复制时产生的,现在主要说明以下问题: 1.如果修改删除master.info文件,复制会中断么? 不会,如果stop slav ...

  8. MySQL面试宝典

    ==============================================# 参数==============================================auto ...

  9. Mysql 主从主主复制总结(详细)

    环境:Centos 6.9,Mysql 8.0 配置准备:1.为Centos配置好网络,使用远程工具连接. 2.安装mysql,途径不限.mysql8.0和5.7区别不大,8.0在配置主从的时候默认开 ...

随机推荐

  1. Mysql的read_only 只读属性说明 (运维笔记)

    在MySQL数据库中,在进行数据迁移和从库只读状态设置时,都会涉及到只读状态和Master-Slave主从关系设置, 以下针对real_only只读属性做些笔记记录: 1) 对于MySQL单实例数据库 ...

  2. 【IT笔试面试题整理】链表

    如何准备 Linked list questions are extremely common These can range from simple (delete a node ina linke ...

  3. android开发学习笔记系列(3)--ScrollView与HorizontalScrollView

    ScrollView与HorizontalScrollView 这是一个滚动视图,就是说如果你在你的UI中容不下那么多的内容,且你对自己的UI都已经设置好了px,OK,那么在适应屏幕过程中,我们并不希 ...

  4. SpringMVC之@PathVariable 映射 URL 绑定的占位符

    @PathVariable 该注解可以将URL中占位符参数绑定到方法的参数上,及ULR中{xxx}可以通过@PathVariable("xxx")绑定到方法参数中. 测试类: @R ...

  5. 【转】学习使用:before和:after伪元素

    如果你一直密切关注着各种网页设计的博客,你可能已经注意到了:before和:after伪元素已经在前端开发中获得了相当多的关注.特别是在Nicolas Gallagher的博客中,后期运用了很多伪类元 ...

  6. C++中的 CONST 含义(从#define 到 CONST 的转变)

    const 与define 两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些.#define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似 ...

  7. net 反射30分钟速成

    概述 什么是反射 Reflection,中文翻译为反射.        这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’.‘模块(Module)’. ...

  8. groovy编程注意事点

    集合中一些方法工作在集合的一个副本上并且完成的时候返回这个副本,而另外一些方法直接操作这个集合对象. 和Java一样不能通过迭代移除元素. list和map遵循java规则限制,但通过附加的方法降低了 ...

  9. linux_shell_数组

    shell数组类似与C语言,数组下标由0开始编号.想要获取数组中的元素要利用下标. 1.首先定义数组 在shell中,用括号来表示数组,数组元素用“空格”符号分割开.列: name=("d& ...

  10. 如何启动一个Vue2.x项目

    1. cd到工作目录2. npm init -y3. 先查看有没有安装全局的vue-cli,:vue-V,没有的话安装一下:npm install vue-cli4. 创建项目: vue init w ...