背景:

今天无意当中看到参数slave_exec_mode,从手册里的说明看出该参数和MySQL复制相关,是可以动态修改的变量,默认是STRICT模式(严格模式),可选值有IDEMPOTENT模式(幂等模式)。设置成IDEMPOTENT模式可以让从库避免1032(从库上不存在的键)和1062(重复键,需要存在主键或则唯一键)的错误,该模式只有在ROW EVENT的binlog模式下生效,在STATEMENT EVENT的binlog模式下无效。IDEMPOTENT模式主要用于多主复制和NDB CLUSTER的情况下,其他情况不建议使用。从上面的介绍来看,这个参数的让从库跳过指定的错误,那问题来了:

1:和sql_slave_skip_counter 比,有什么好处?

2:和 slave-skip-errors = N比,有什么好处?

带着这2个问题,本文来进行相关的测试和说明。

环境:

MySQL版本:Percona MySQL 5.7

复制模式:ROW,没有开启GTID

测试:

① 1062 错误:Could not execute ... event on table db.x; Duplicate entry 'xx' for key 'PRIMARY', Error_code: 1062;

主从上的测试表结构:

CREATE TABLE`x` (

`id`int(11) NOT NULLAUTO_INCREMENT,PRIMARY KEY(`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

主从上的表记录:

M:

select * fromx;+----+

| id |

+----+

| 2 |

| 3 |

+----+

2 rows in set (0.01 sec)

S:

select * fromx;+----+

| id |

+----+

| 1 |

| 2 |

| 3 |

+----+

3 rows in set (0.00 sec)

主从上的表记录本来就不一致了,主上缺少了id=1的记录。

此时从上的slave_exec_mode为默认的STRICT模式:

show variables like 'slave_exec_mode';+-----------------+--------+

| Variable_name | Value |

+-----------------+--------+

| slave_exec_mode | STRICT |

+-----------------+--------+

1 row in set (0.00 sec)

M上的binlog模式为:

show variables like 'binlog_format'; +---------------+-------+

| Variable_name | Value |

+---------------+-------+

| binlog_format | ROW |

+---------------+-------+

1 row in set (0.00 sec)

在M上执行:

insert into x values(1),(4),(5);

Query OK,3 rows affected (0.00sec)

Records:3 Duplicates: 0 Warnings: 0

因为从上已经存在了id=1的记录,此时从的复制就报了1062的错误:

Last_SQL_Errno: 1062Last_SQL_Error: Couldnot execute Write_rows event on table dba_test.x; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin-3306.000006, end_log_pos 7124

出现这个错误时,大家的一致做法就是执行:sql_slave_skip_counter=N。关于该参数的说明可以看

1、set global sql_slave_skip_counter=N中的N是指跳过N个event2、最好记的是N被设置为1时,效果跳过下一个事务。3、跳过第N个event后,位置若刚好落在一个事务内部,则会跳过这整个事务4、一个insert/update/delete不一定只对应一个event,由引擎和日志格式决定

sql_slave_skip_counter的单位是“event”,很多人认为该参数的单位是“事务”,其实是错误的,因为一个事务里包含了多个event,跳过N个可能还是在同一个事务当中。对于上面出现1062的错误,把N设置成1~4效果是一样的,都是跳过一个事务。因为执行的SQL生成了4个event:

show binlog events in 'mysql-bin-3306.000006' from 6950;+-----------------------+------+------------+-----------+-------------+---------------------------------+

| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |

+-----------------------+------+------------+-----------+-------------+---------------------------------+

| mysql-bin-3306.000006 | 6950 | Query | 169 | 7026 | BEGIN |

| mysql-bin-3306.000006 | 7026 | Table_map | 169 | 7074 | table_id: 707 (dba_test.x) |

| mysql-bin-3306.000006 | 7074 | Write_rows | 169 | 7124 | table_id: 707 flags: STMT_END_F |

| mysql-bin-3306.000006 | 7124 | Xid | 169 | 7155 | COMMIT /*xid=74803*/ |

+-----------------------+------+------------+-----------+-------------+---------------------------------+

4 rows in set (0.00 sec)

所以处理该错误的方法有:

1:skip_slavesql_slave_skip_counter

stop slave; Query OK, 0 rows affected (0.00sec)set global sql_slave_skip_counter=[1-4];

Query OK,0 rows affected (0.00sec)

start slave;

Query OK,0 rows affected (0.00 sec)

2:在配置文件里指定slave-skip-errors=1062(需要重启)

这2种方法都能让复制恢复正常,但是会让主从数据不一致(谨慎使用),让从库丢失了id=4和5的记录。并且第2种方法还需要重启数据库,这时本文介绍的slave_exec_mode参数就派上用场了。在从库上设置该参数:

set global slave_exec_mode='IDEMPOTENT';

Query OK,0 rows affected (0.00sec)

stop slave; Query OK,0 rows affected (0.00sec)

start slave;

Query OK,0 rows affected (0.00 sec)

同样在主上执行:

insert into x values(1),(4),(5);

可以惊喜的发现主从数据是同步的,没有出现复制异常:

M:select * from x; +----+

| id |

+----+

| 1 |

| 2 |

| 3 |

| 4 |

| 5 |

+----+

5 rows in set (0.00sec)

S:select * from x; +----+

| id |

+----+

| 1 |

| 2 |

| 3 |

| 4 |

| 5 |

+----+

5 rows in set (0.01 sec)

上面的测试可以看到,参数设置成slave_exec_mode='IDEMPOTENT' 后,可以跳过出一个错误的event。

② 1032错误:Could not execute ... event on table db.x; Can't find record in 'x', Error_code: 1032;

这个错误的出现是因为ROW模式下的复制,对数据的一致性有了很严的要求,具体的可以看MySQL Binlog 【ROW】和【STATEMENT】选择

主从上的测试表结构:

CREATE TABLE`x` (

`id` int(11) NOT NULLAUTO_INCREMENT,

PRIMARY KEY(`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

主从上的表记录:

M:

select * from x; +----+

| id |

+----+

| 1 |

| 2 |

| 3 |

+----+

3 rows in set (0.00 sec)

S:

select * fromx;

+----+

| id |

+----+

| 1 || 3 |

+----+

2rows in set (0.00 sec)

主从上的表记录本来就不一致了,从上缺少了id=2的记录。此时从上的slave_exec_mode为默认的STRICT模式:

show variables like 'slave_exec_mode';

+-----------------+--------+

| Variable_name | Value |

+-----------------+--------+

| slave_exec_mode | STRICT |

+-----------------+--------+

1 row in set (0.00 sec)

M上的binlog模式为:

show variables like 'binlog_format'; +---------------+-------+

| Variable_name | Value |

+---------------+-------+

| binlog_format | ROW |

+---------------+-------+

1 row in set (0.00 sec)

在M上执行:

BEGIN;INSERT INTO x SELECT 4;DELETE FROM x WHERE id = 2;INSERT INTO x SELECT 5;COMMIT;

因为从上不存在了id=2的记录,此时从的复制就报了1032的错误:

Last_SQL_Errno: 1032Last_SQL_Error: Couldnot execute Delete_rows event on table dba_test.x; Can't find record in'x', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin-3306.000006, end_log_pos 12102

同样的,在上面测试中说明的2种方法可以让复制正常,但是数据也一样会丢失。丢失了id=4和5的记录,继续在从库上设置该参数:

set global slave_exec_mode='IDEMPOTENT';

Query OK,0 rows affected (0.00sec)

stop slave; Query OK,0 rows affected (0.00sec)

start slave;

Query OK,0 rows affected (0.00 sec)

在M上执行同样的操作:

BEGIN;INSERT INTO x SELECT 4;DELETE FROM x WHERE id = 2;INSERT INTO x SELECT 5;COMMIT;

也可以惊喜的发现主从数据是同步的,没有出现复制异常。

注意:

总结:

对于上面的测试总结,针对slave_exec_mode参数,它可以跳过1062和1032的错误,并且不影响同一个事务中正常的数据执行。如果是多个SQL组成的事务,则可以跳过有问题的event。

看着这个参数很不错,但手册上说明不建议在普通的复制环境中开启。对于NDB以外的存储引擎,只有在确定可以安全地忽略重复键错误和没有键的错误时,才应使用IDEMPOTENT模式。这参数是专门针对NBD Cluster进行设计的,NBD Cluster模式下,该参数只能设置成IDEMPOTENT模式。所以要根据自己的应用场景来决定,正常情况下,主从是一致的,有任何错误发生都要报错,不过在做特殊处理时,可以临时开启。

另外在GTID模式下的复制,sql_slave_skip_counter是不支持的,该模式下的复制可以自行测试。

mysql变量 exec_MySQL slave_exec_mode 参数说明相关推荐

  1. mysql declare 赋值_sql server和mysql变量赋值的区别 以及 MySql Declare(转)

    sql server和mysql都是我们经常用到的数据库系统,下面就为您介绍sql server和mysql变量赋值的区别,希望对您能有所启迪. sql server中变量要先申明后赋值: 局部变量用 ...

  2. mysql变量使用总结

    使用select定义用户变量的实践 将如下语句改成select的形式:  set @VAR=(select sum(amount) from penalties); 我的修改:  select @VA ...

  3. mysql 变量作用域_二十二、MySQL基础系列笔记之变量

    什么MySQL变量 MySQL本质是一种编程语言,变量用来存储数据. 与所有语言一样,变量是用来存储数据的.我们平常所写的SQL语句,实际上是在SQL编程. MySQL两种变量 MySQL变量分为系统 ...

  4. mysql 修改配置生效_linux下面MySQL变量修改及生效

    今天在访问mysql项目的时候突然报500错误,没有找到连接,因此想到mysql的连接时间. mysql> show global variables; 主要就是连接时间是28800(8小时), ...

  5. mysql php 变量赋值,mysql变量赋值要注意的_MySQL

    bitsCN.com mysql变量赋值要注意的 mysqlsql 今天由于项目需要,需要写个存储过程,这个可是一年才难得写一次.于是没办法,重新捡起来.开始写 写到后来.. Sql代码 CREATE ...

  6. mysql数据库的变量有哪些_[数据库]MySQL变量

    [数据库]MySQL变量 0 2021-02-08 04:01:23 原文链 id="mysql变量">MySQL变量 MySQL变量分为系统变量和自定义变量 系统变量 系统 ...

  7. mysql declare 赋值_sql server和mysql变量赋值的区别 以及 MySql Declare

    sql server和mysql都是我们经常用到的数据库系统,下面就为您介绍sql server和mysql变量赋值的区别,希望对您能有所启迪. sql server中变量要先申明后赋值: 局部变量用 ...

  8. linux mysql更改生效_linux下面MySQL变量修改及生效

    今天在访问mysql项目的时候突然报500错误,没有找到连接,因此想到mysql的连接时间. mysql> show global variables; 主要就是连接时间是28800(8小时), ...

  9. mysql 大量列 动态变量_aardio动态mysql变量设置

    aardio动态mysql变量设置 aardio动态mysql变量设置 废话不多说,直接开始干活! 从上午度娘到现在!终于有点结果! 需求是从数据库读取数据,根据条件(变量) 直接上代码,如有任何问题 ...

最新文章

  1. 智力题:关于进入房间一次,判断哪个开关控制哪盏灯的问题
  2. 晒加班晒熬夜……“晒勤奋”是一种病!
  3. Ubuntu下嵌入式Qt开发环境配置全攻略
  4. [css] 使用css3画一个扇形
  5. CCNA-第九篇-OSPF下+VLAN开篇初介绍
  6. 计算机组组内培训记录,计算机教研组活动记录.doc
  7. 1105学习笔记 数组的算法上
  8. iPhone 13系列又有新配色:猛男必看!
  9. 水面反光如何拍摄_如何抓拍水的不同瞬间
  10. DiscuzNT改造系列之删除帖子后论坛版块列表同步更新
  11. 基于路径跟随的纯跟踪算法--差速模型
  12. 华为od德科面试数据算法解析 2022-3-20 关于员工工号问题
  13. 阿里云对象存储OSS
  14. 思维导图告诉你怎样正确的做笔记?
  15. 查看CAD图纸文件时如何平移查看?
  16. java white case语句_JAVA基础(一)
  17. java learn 日期
  18. OpenCV显示MNIST中的手写图片
  19. Amdahl(阿姆达尔定律) Law
  20. 如何查看线程的详细信息

热门文章

  1. C++::探索对象模型
  2. 原始socket例子
  3. 【操作系统】进程调度(2b):STCF(最短完成时间优先) 算法 原理与实践
  4. 【转】DCOM远程调用权限设置
  5. JavaScript实现职责链模式
  6. 数据下发非标准用户权限测试
  7. NeHe OpenGL教程 第三十七课:卡通映射
  8. 在package.json里面的script设置环境变量,区分开发及生产环境。注意mac与windows的设置方式不一样...
  9. WPF Slider设置整数
  10. springmvc常用注解之@Controller和@RequestMapping