【MySql】sql_slave_skip_counter 参数的用法解析

 前一篇文章介绍了当mysql的复制出现slave sql 进程终止时的解决办法,其中之一使用了 sql_slave_skip_counter 来使sql 线程跳过遇到错误的事件记录!本文浅析一下 sql_slave_skip_counter的具体用法和意义!
set global sql_slave_skip_counter = N
This statement skips the next N events from the master. 
(即是跳过N个events,这里最重要的是理解event的含义!在mysql中,对于sql的 binary log 实际上是由一连串的event组成的一个组,即事务组。)
在备库上设置 global sql_slave_skip_counter =N 会跳过当前时间来自于master的之后N个事件,这对于恢复由某条SQL语句引起的从库复制有效. 此语句只在当slave threads是停止时才有效,否则将发生一条错误..每忽略一个事件,N 减一,直到N减为0!
When using this statement, it is important to understand that the binary log is actually organized as a sequence of groups known as event groups. Each event group consists of a sequence of events.
For transactional tables, an event group corresponds to a transaction.
For nontransactional tables, an event group corresponds to a single SQL statement.
Note
   A single transaction can contain changes to both transactional and nontransactional tables.When you use SET GLOBAL sql_slave_skip_counter to skip events and the result is in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group
### comment ###
   Setting this variable isn't like setting other server variables: you can't read the variable back again as @@sql_slave_skip_counter, and it isn't really a "global variable." Rather, it's a variable that only the slave thread reads.
  When you restart the slave threads again with START SLAVE, the slave skips statements and decrements the variable until it reaches 0, at which point it begins executing statements again. You can watch this happening by executing SHOW SLAVE STATUS, where the variable's value appears in the Skip_Counter column. This is the only place you can see its value.
  The effect is that the setting isn't persistent. If you set it to 1, start the slave, and the slave has an error in replication sometime later, the variable won't still be set to 1. It'll be 0. At that point, if you want the slave to skip the statement that caused the error, you'll have to set it to 1 again.
有关"SET GLOBAL sql_slave_skip_counter"的语法可以参考官方文档
测试环境:
rac3 主库
rac4 备库
测试之前保证主从无数据延时,保证数据一致!
1 使用含有 stop slave 的命令, 在主库上创建测试表,并使用shell 插入数据!
mysql> create table tab_skip(id int);
Query OK, 0 rows affected (0.80 sec)
[root@rac3 mysql]#
 for i in {1..100}; 
   do 
    echo $i; 
    echo "insert into tab_skip(id) values($i)" | mysql -h127.0.0.1 test ; 
    sleep 1;
done;
在备库 使用 set global sql_slave_skip_counter=1;命令做测试
[root@rac4 mysql]# 
for i in {1..10}; 
do 
   echo $i; 
   echo "slave stop;set global sql_slave_skip_counter=1; slave start;show slave status\G" | mysql -h127.0.0.1 -P3306 test ; 
   sleep 2;
done;
分别在主库和备库上进行验证数据的完整性:
主库上面:
[root@rac3 mysql]# mysql
mysql> use test;                 
Database changed
mysql> select count(1) from tab_1;
+----------+
| count(1) |
+----------+
|      100 |
+----------+
1 row in set (0.00 sec)
备库上面,少了 10条数据!因为正是执行set global sql_slave_skip_counter=1;使备库执行sql replay的时候忽略了事件!
[root@rac4 mysql]# mysql
mysql> use test;
Database changed
mysql> select count(1) from tab_1;  
+----------+
| count(1) |
+----------+
|       90 |
+----------+
1 row in set (0.00 sec)

有网友测试的是在备库上执行没有stop slave 语句的命令,但是在5.5.18版本上面是不允许的!
[root@rac3 mysql]# for i in {1..100}; do echo $i; echo "insert into tab_2(id) values($i)" | mysql -h127.0.0.1 test ; sleep 2;done;   
1
....
100

在备库上执行,注:"set global sql_slave_skip_counter=1; slave start;show slave status\G"  没有stop slave 语句,报错!
[root@rac4 mysql]# for i in {1..10}; do echo $i; echo "set global sql_slave_skip_counter=1; slave start;show slave status\G" | mysql -h127.0.0.1 -P3306 test ; sleep 2;done;          
1
ERROR 1198 (HY000) at line 1: This operation cannot be performed with a running slave; run STOP SLAVE first
2
ERROR 1198 (HY000) at line 1: This operation cannot be performed with a running slave; run STOP SLAVE first
3
ERROR 1198 (HY000) at line 1: This operation cannot be performed with a running slave; run STOP SLAVE first
4
ERROR 1198 (HY000) at line 1: This operation cannot be performed with a running slave; run STOP SLAVE first

使用 该参数能够解决从服务器sql 进程停止导致的数据库不同步,但是也有一定的风险,比如在高并发的数据库环境下,可能会导致数据丢失!
另见另一位网友的 测试实验 (多少有些出入,他的可以不使用stop slave)



补充比较好的一点概念

背景知识1:
    在主从库维护中,有时候需要跳过某个无法执行的命令,需要在slave处于stop状态下,执行 set global sql_slave_skip_counter=N以跳过命令。常用的且不易用错的是N=1的情况,但N>1时,则不那么顾名思义,本文详细介绍N的意义,及使用注意事项。
 
    背景知识2:
    MySQL从库从主库上复制binlog文件内容到本地执行。在binlog上命令以event的形式存在,并非一个命令对应一个event。以一个insert语句为例(引擎InnoDB、binglog_format=statement), 在binlog中实际上有三个event,分别为begin\insert\commit 。 命令类型都是Query_log_event.
 
    而set global sql_slave_skip_counter=N的意思,即为在start slave时,从当前位置起,跳过N个event。每跳过一个event,则N--.
 
    与实际情况不符?
    看到这里有同学就会问,这是有问题的。如果当前的执行位置是某个insert语句开头,那使用 N=1实际上是从begin\insert\commit的第二个开始执行,这个insert语句还是不能被跳过?
    实际上这里还有两个策略:
    1、若N=1且当前event为BEGIN, 则N不变,跳过当前event继续。
    2、若N=1且当前event处于一个事务之内(BEGIN之后,COMMIT之前),则N不变,跳过当前event继续。
 
     说明:其实上面两个策略合起来就是一句话,当N=1时,会连续跳过若干个event,直到当前所在的事务结束。
    当然如果N>1,则每跳过一个event都要N--.  
    命令举例:
    所以我们平时最常用的N=1的情况,都是下一个事务。
    假设某个Pos之后执行如下命令( 引擎InnoDB、binglog_format=statement)
    insert into t values(x1);
    begin;
    insert into t values(x2);
    insert into t values(x3);
    commit;
   insert into t values(x4);
你的从库stop在Pos上,假设你要跳过前面几个命令直接执行插入x4的操作,则你的N设置为 4或5或6或7均可。(X1语句为3个event)
 
   其他说明:
   上面举例中都特别说明了在innodb引擎和statement模式下。其他情况区别如下:
   1、若引擎为myisam(等不支持事务的引擎),且在statement下,则binlog中不会有begin和commit,每个命令都是一个event;
   2、row模式的binlog里,一个insert语句实际上是两个event(Table_map_event和 Row_log_event), 计算时应与statement不同。
  3、在row模式下,不论引擎是否支持事务,一个insert语句都会加上BEGIN和commit,也即变成4个event。
  4、基于InnoDB引擎表的insert/delete/update操作都有显式样的BEGIN /COMMIT.
 
  上面举的这个例子中,若为row模式,则要直接执行X4语句需要设置的N为 5~10均可。
 
   小结:
   1、set global sql_slave_skip_counter=N中的N是指跳过N个event
   2、最好记的是N被设置为1时,效果跳过下一个事务。
   3、跳过第N个event后,位置若刚好落在一个事务内部,则会跳过这整个事务
   4、一个insert/update/delete不一定只对应一个event,由引擎和日志格式决定


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29096438/viewspace-1809174/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29096438/viewspace-1809174/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值