[转]小心,前方有雷 —— sql_slave_skip_counter
最近数据库服务器多事之秋,莫名的批量宕机事件一再发生,搞得压力超大。厂商来了之后也酥手无策。上周路过寺庙,平生第一次感叹道是否要去烧烧香,拜托拜托数据库之神能让我们团队早日度过这个劫难。
上周和William聊到MySQL的参数sql_slave_skip_counter,感叹很多人并没有真正了解这个参数的含义。面试时这是一个很好的问题,相信即使是淘宝P7的level,要准确答对这个问题也是需要平时的细心累积。
01
很多同学的误区在于会把参sql_slave_skip_counter=N理解成跳过N个事务。如果这样的回答,至少在我心中已经扣分不少,要拿高P几乎不可能。首先看看文档中的定义:
SET GLOBAL sql_slave_skip_counter = N
This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.
官方文档中明确指出N表示的是N个event。很多同学把这个参数的单位理解成事务的原因在于他把操作都理解成了由单条语句所组成的事务。这时N的含义两者等价。
然而,更常见的场景却是一个事务可能由多个EVENT组成,例如一个事务可以有多个SQL组成,例如:
BEGIN; INSERT ...;DELETE ...; INSERT; COMMIT;
若这时将N理解成事务,那么结果就会非常不同。当然,答对参数sql_slave_skip_counter的单位是事务,这个答案也仅只有60分。
02
如果细看文档的话,文档最后一段还说道:
When you use SET GLOBAL sql_slave_skip_counter to skip events and the results 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.
这句非常关键,也就是说可能上面的答案是:以上全错。N可以不表示跳过N个事务,甚至可能是跳过>=N个事务的场景。假设开始时主、从的数据分别为:
Master
| Slave |
|---|
| a |
| 1 |
| 2 |
| 3 |
+----+ +----+
| a |
|---|
| 1 |
| 3 |
由于主从数据已然不一致,这时若在主上执行下面的SQL:
BEGIN;
INSERT INTO Z SELECT 4;
DELETE FROM Z WHERE a = 2;
INSERT INTO Z SELECT 5;
COMMIT;
从机显然会报错,提示1032错误,因为记录2这条记录并没有找到。这时的处理方法很多DBA会选择执行SET GLOBAL sql_slave_skip_counter=1。然而,这样的处理会导致INSERT 5这条记录不被执行。因为跳过DELETE 2这个操作后,事务没有结束,会继续跳过接下去的event,这就是文档中说的:the slave continues to skip events until it reaches the end of the group。感兴趣的同学可以自行测试看看最终的结果。
若只想跳过一个EVENT该怎么做呢?其实,只需将参slave_exec_mode设置为IDEMPOTENT即可。
03
出现主从复制出错,最安全的方法还是重建从机。另外,MySQL的复制早就是crash safe的复制机制了。若你的复制环境经常出错,应该好好检查下数据库的配置参数。
对于参数sql_skip_slave_counter来说,这只是一个不得已为之的方法。同时,当开启GTID模式时,也无法通过参数进行跳过出错的EVENT。
原文:https://mp.weixin.qq.com/s/rZZbLmN0Klq0o0bvnijizw
版权属于:Joyber
本文链接:https://blog.qqvbc.com/default/410.html
转载时须注明出处及本声明