Mysql主从复制之slave_exec_mode,slave_skip_errors参数详解和测试

参数)slave_exec_mode 
slave_exec_mode = STRICT
MySQL主从同步中,经常遇到的三种同步错误:
1、在master上delete一条记录,若在slave上没有这条数据,会出现报错。
2、在master上insert一条记录,若在slave上主键值已经存在,会出现报错。
3、在master上update一条记录,若在slave上没有这条数据,会出现报错。
如果slave的my.cnf已经配置了slave_skip_errors参数,则可以自动跳过报错,如果没有配置该参数,则可以用以下方法解决:
mysql> set global slave_exec_mode='idempotent'; 
默认值是strict(严格模式),IDEMPOTENT  模式跳过主键冲突错误和更新删除行不存在错误。

参数)slave_skip_errors选项有四个可用值,分别为: off,all,ErorCode,ddl_exist_errors 。
     默认情况下该参数值是off,我们可以列出具体的error code,也可以选择all,mysql5.6及MySQL Cluster NDB 7.3以及后续版本增加了参数ddl_exist_errors,该参数包含一系列error code(1007,1008,1050,1051,1054,1060,1061,1068,1094,1146)
    一些error code代表的错误如下:
     1007: 数据库已存在,创建数据库失败
     1008: 数据库不存在,删除数据库失败
     1050: 数据表已存在,创建数据表失败
     1051: 数据表不存在,删除数据表失败
     1054: 字段不存在,或程序文件跟数据库有冲突
     1060: 字段重复,导致无法插入
     1061: 重复键名
     1068: 定义了多个主键
     1094: 位置线程ID
    1146: 数据表缺失,请恢复数据库
    1053: 复制过程中主服务器宕机
     1062: 主键冲突 Duplicate entry '%s' for key %d


 测试:slave_exec_mode = STRICT 不设置slave_skip_errors参数
 
 场景1)在主库插入一条数据,然后从库删除这条数据,然后主库再删除这条数据,从库会报错:
 Last_SQL_Error: Could not execute Delete_rows event on table mytest1.log_test; Can't find record in 'log_test', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's master log mysql-bin.000026, end_log_pos 1136
 场景2)在主库创建一个主库表,然后在从库先插入一条数据,然后再主库插入这条数据,从库会报错:
       Last_SQL_Error: Could not execute Write_rows event on table mytest1.log_test_new; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000026, end_log_pos 2859
 场景3)在主库插入一条数据,然后从库删除这条数据,然后主库再更新这条数据,从库会报错:
   Last_SQL_Error: Could not execute Update_rows event on table mytest1.log_test; Can't find record in 'log_test', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's master log mysql-bin.000026, end_log_pos 2509


  测试:slave_exec_mode = STRICT 设置slave_skip_errors参数为ALL
  场景1)在主库插入一条数据,然后从库删除这条数据,然后主库再删除这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
   Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 4514
  场景2)在主库创建一个主库表,然后在从库先插入一条数据,然后再主库插入这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
         Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 5195
 场景3)在主库插入一条数据,然后从库删除这条数据,然后主库再更新这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
  Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 5876

测试:slave_exec_mode = idempotent 不设置slave_skip_errors参数
[root@localhost:mytest1]>show variables like '%slave_skip_errors%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| slave_skip_errors | OFF   |
+-------------------+-------+
1 row in set (0.01 sec)

[root@localhost:mytest1]>select count(*) from log_test1 where id>80000000;^C
[root@localhost:mytest1]>show variables like '%slave_exec_mode%';
+-----------------+------------+
| Variable_name   | Value      |
+-----------------+------------+
| slave_exec_mode | IDEMPOTENT |
+-----------------+------------+
1 row in set (0.00 sec)

场景1)在主库插入一条数据,然后从库删除这条数据,然后主库再删除这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
    Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 6194
  场景2)在主库创建一个主库表,然后在从库先插入一条数据,然后再主库插入这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
          Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 6875
 场景3)在主库插入一条数据,然后从库删除这条数据,然后主库再更新这条数据,从库不会报错,Read_Master_Log_Pos看到会执行完这个sql
    Master_Log_File: mysql-bin.000026
          Read_Master_Log_Pos: 7556

 下面我们来做一组关于slave_exec_mode='idempotent' 更详细的测试

mysql> create table test_idempotent(id int not null primary key,name varchar(10));
Query OK, 0 rows affected (0.02 sec)

[root@localhost:mytest1]>select * from test_idempotent;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
|  3 | wangwu   |
|  4 | zhaoliu  |
+----+----------+
4 rows in set (0.00 sec)

1.从库删除id=1的行,主库再删除id=1的行,slave复制不会报错
 [root@localhost:mytest1]>delete from test_idempotent where id=1;
Query OK, 1 row affected (0.01 sec)
   
    2。从库删除id=2的行,主库再更新id=2的行,slave复制不会报错
[root@localhost:mytest1]>delete from test_idempotent where id=2;
Query OK, 1 row affected (0.01 sec)

3.从库插入id=1的行,主库再插入id=1的行,slave复制不会报错,而且从库将原id=1的行删除,然后插入了主库的行
[root@localhost:mytest1]>insert into test_idempotent values(1,'zhangsan');
Query OK, 1 row affected (0.01 sec)


主库 [root@localhost:mytest1]>insert into test_idempotent values(1,'zhangsan88');
Query OK, 1 row affected (0.01 sec)
从库:
[root@localhost:mytest1]>select * from test_idempotent;
+----+------------+
| id | name       |
+----+------------+
|  1 | zhangsan88 |
|  3 | wangwu     |
|  4 | zhaoliu    |
+----+------------+
3 rows in set (0.00 sec)

  而我们再次在从库手动插入id=1的行时,会报主键冲突
[root@localhost:mytest1]>insert into test_idempotent values(1,'zhangsan');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

4.从库插入id=2的行,主库再更新id=1的行成为id=2,slave复制不会报错,而且会跳过这个sql
 目标: [root@localhost:mytest1]>insert into test_idempotent values (2,'lisi');
Query OK, 1 row affected (0.01 sec)

[root@localhost:mytest1]>select * from test_idempotent;
+----+------------+
| id | name       |
+----+------------+
|  1 | zhangsan88 |
|  2 | lisi       |
|  3 | wangwu     |
|  4 | zhaoliu    |
+----+------------+
4 rows in set (0.00 sec)

 主库:
 mysql> select * from test_idempotent;
+----+------------+
| id | name       |
+----+------------+
|  1 | zhangsan88 |
|  3 | wangwu     |
|  4 | zhaoliu    |
+----+------------+
3 rows in set (0.00 sec)
mysql> update test_idempotent set id=2 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

从库:
[root@localhost:mytest1]>select * from test_idempotent;
+----+------------+
| id | name       |
+----+------------+
|  1 | zhangsan88 |
|  2 | lisi       |
|  3 | wangwu     |
|  4 | zhaoliu    |
+----+------------+
4 rows in set (0.00 sec)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值