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. Java多线程同步集合--并发库高级应用

    一.阻塞队列1.在多线程领域,所谓阻塞,在某些情况下会挂起线程,一旦条件满足,被挂起的线程又会自动被唤醒2.ArrayBlockingQueue(效率高)和LinkedBlockingQueue是两个 ...

  2. Spring <context:component-scan>标签属性 use-default-filters 以及子标签 include-filter使用说明

    Spring <context:component-scan>标签作用有很多,最基本就是 开启包扫描,可以使用@Component.@Service.@Component等注解: 今天要作 ...

  3. MWeb 生成静态网站&博客

    MWeb 生成静态网站 & 博客 MWeb 的静态网站分类 在 MWeb 的文档库中,有两种分类,一种是普通分类,另一种就是静态网站分类了.你可以直接新增一个静态网站分类,也可以在普通分类的顶 ...

  4. C# Claims-based(基于声明)的认证

    本文是通过验证与网上资料整合的,请读者注意. 目录: 1. 什么是Claims-based认证 2.进一步理解Claims-based认证 3.Claims-based的简单demo 1. 什么是Cl ...

  5. 使用iframe实现同域跨站提交数据

    有一个已经编译的asp.net 1.1的网站.为了改进录入的效率,改为由barcode扫描枪来替代手动.由于在扫描枪添加其它信息.原录入窗口已经无法适应.另外程序虽然跑的是存储过程,但交易的trans ...

  6. 3.Decorator Pattern(装饰者模式)

    装饰者模式: 动态地将责任附加到对象上.想要扩展功能,装饰者提供有别于继承的另一种选择. 举例: 不知道大家学校的食堂是什么点餐制度(或者大家就直接想成吃火锅,我们要火锅料 + 配菜),我们学校的点餐 ...

  7. Maven 那些破事

    deploy 只上传了pom 晚上输命令,打算打包上传到本地库里,然后去服务器上部署新版本 mvn clean package deploy 结果看着mvn的build过程只是上传了pom,去库服务器 ...

  8. django-缓存的应用

    为什么需要缓存? django中文文档: 通常,计算值是昂贵的(即资源匮乏和缓慢),因此将值保存到可快速访问的缓存中可以有巨大的好处,为下一次需要做好准备. 这是一个足够重要和强大的技术,Django ...

  9. Mysql数据库 的库表简易操作

    一. 库的操作 1.创建数据库 创建数据库: create database 库名 charset utf8;   charset uft8  可选项 1.2 数据库命名规范: 可以由字母.数字.下划 ...

  10. Unable to open debugger port (127.0.0.1:63777): java.net.BindException "Address

    困扰了我好久,试过删掉taget文件夹rebuild,不删除Tomcat Server配置手动修改端口号也不行,试过杀掉java进程和重启机器,但是就是没效果. 解决: 删除Tomcat Server ...