• 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)

  • 相关阅读:
    SpringCloud学习笔记-gateway网关自定义全局过滤器
    linux安装nodejs
    响应式布局(3种) + flex计算
    Python中关闭文件很重要
    物联网的10个初级术语
    c语言练习44:深入理解strstr
    ESP8266,手机与电脑之间的TCP通讯
    apache配置https证书问题记录
    Apache阿帕奇安装配置
    Python网络爬虫5-实战网页爬取
  • 原文地址:https://blog.csdn.net/liys0811/article/details/132836669