MySQL跳过 1032 1062错误

传统复制情况
  1. slave_exec_mode(global级别) IDEMPOTENT or STRICT

    Controls how a slave thread resolves conflicts and errors during replication. IDEMPOTENT mode causes suppression of duplicate-key and no- key-found errors; STRICT means no such suppression takes place.

    IDEMPOTENT mode is intended for use in multi-master replication, circular replication, and some other special replication scenarios for NDB Cluster Replication. (See Section 21.6.10, “NDB Cluster Replication: Multi-Master and Circular Replication”, and Section 21.6.11, “NDB Cluster Replication Conflict Resolution”, for more information.) NDB Cluster ignores any value explicitly set for slave_exec_mode, and always treats it as IDEMPOTENT.

    In MySQL Server 5.7, STRICT mode is the default value.

    or storage engines other than NDB, IDEMPOTENT mode should be used only when you are absolutely sure that duplicate-key errors and key-not-found errors can safely be ignored. It is meant to be used in fail-over scenarios for NDB Cluster where multi-master replication or circular replication is employed, and is not recommended for use in other cases.

    • 在IDEMPOTENT(幂等)模式的情况下的情况(一个事务内部3个SQL,中间的SQL语句在严格(STRICT)的模式下面会发生1062或者1032错误)
      • 这个参数针对传统复制还是GTID复制的效果还是一样的
      • 针对1062主键冲突的错误,无论binlog_format是ROW格式还是STATEMENT格式,从库发生主键冲突的行的值都会被主库同步过来的数据给覆盖掉,即认为在从库执行replace操作。
      • 针对1032行找不到的错误,无论binlog_format是ROW格式还是STATEMENT格式,从库本地都会忽略这条SQL语句,不执行,只是执行事务的其他没有错误的SQL。
  2. sql_slave_skip_counter(global级别)
    • 这个参数只是针对传统复制有效,针对GTID复制只能使用gtid_next.
    • 在binlog_format为ROW格式的情况下,在出现1032或者1062的情况下,并且table存在自增健为主键,并且在master上面执行insert操作的时候没有指定主键,这个时候需要注意主键的键值信息,很有可能在出现1032或者1062错误跳过之后master和slave俩者的主键下一个键值可能不一致。所以需要注意的操作有delete,insert,truncate。
    • 参数针对的单位是statment还是row。若是针对statement的话,那么在一个事务内部执行多条statement的话,遇到1032或者1062这种错误的话是有没有如下三种情况:
      • 整个事务都会跳过不会执行,在这个statement前面已经执行的也会回滚。
      • 只是会跳过报错的那条statement,后续还有statement的话还会继续执行。
      • 会跳过报错的那条statement和后续所有的还没有执行的statement,但是前面已经执行成功的statement不会回滚。
    • 在binlog_format的格式是ROW格式的情况下面,无论是1032还是1062情况下设置sql_slave_skip_counter=1,它会将整个事务跳过去。
    • 在binlog_format的格式是statement的情况下,sql_slave_skip_counter=1并且是1062的错误,它会将整个事务跳过去。
    • binglog_format的格式是statement的情况下,针对1032错误,在整个事务当中出现修改一个主库存在,但是从库不存在的row的数据的时候,在从库是不会报错的,并且这事务的其他语句是可以成功执行的。
  3. slave_skip_errors(global级别) 这个参数暂时还是只读参数,不能动态修改,要想修改的话必须在配置文件里面修改并且重启数据库实例才会生效。

    • 这个参数针对gtid和传统复制有效,并且俩者的结果都一样。报错的SQL语句会跳过,但是其余的SQL还是正常执行。
    • 设置slave_skip_errors=1062或者1032在binlog_format是statement的情况下,整个事务只会跳过报1062或者1032错误的sql,不执行这条SQL,其余的sql正常进行。
    • 设置slave_skip_errors=1062或者1032在binlog_format是ROW的情况下,整个事务只会跳过报1062或者1032错误的sql,不执行这条SQL其余的sql正常进行。
  4. 总结:
GTID复制
  1. gtid_next(session级别)
    • GTID模式的下
    • 在master获取GTID执行的信息:
mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------------------------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                            |
+------------------+----------+--------------+------------------+----------------------------------------------------------------------------------------------+
| mysql-bin.000026 |     4347 |              |                  | 834f1e16-fa69-11e7-b271-000c291f2799:1-1013108,
b7737e22-e469-11e7-b6b9-000c29a80f41:1-94000 |
+------------------+----------+--------------+------------------+----------------------------------------------------------------------------------------------+
  • 在slave获取未执行GTID信息:主要是观察Retrieved_Gtid_Set和Executed_Gtid_Set的值
mysql> show slave status \G
......
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 73306
                  Master_UUID: 834f1e16-fa69-11e7-b271-000c291f2799
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 834f1e16-fa69-11e7-b271-000c291f2799:1013102-1013108
            Executed_Gtid_Set: 069020a4-d346-11e7-a9e6-000c2920ceb4:1-123487,
69d937df-dbfe-11e7-84e5-000c291f2799:1-2,
834f1e16-fa69-11e7-b271-000c291f2799:1-1013107,
b7737e22-e469-11e7-b6b9-000c29a80f41:1-94000,
f1542f99-0015-11e8-a7c3-000c29a80f41:1-6
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
......
  • 在slave设置空的gtid值
root@mysqldb 16:12:  [percona]> show variables like '%next%';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| gtid_next     | AUTOMATIC |
+---------------+-----------+
1 row in set (0.00 sec)
root@mysqldb 16:14:  [percona]> set gtid_next='834f1e16-fa69-11e7-b271-000c291f2799:1013108';
Query OK, 0 rows affected (0.00 sec)

root@mysqldb 16:14:  [percona]> begin;commit;
Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.02 sec)

root@mysqldb 16:14:  [percona]> set gtid_next='AUTOMATIC';
Query OK, 0 rows affected (0.00 sec) 
  • 重启slave

20180612 补充

固定路数应该是从从库的报错信息中获取得到当前报错的schema,table,primary key定义到具体的row出现主键冲突,然后在slave上面删除这行数据,再重新启动slave的SQL_THREAD进程。