跳过复制错误——slave_skip_errors、slave_exec_mode-程序员宅基地

技术标签: 开发工具  数据库  

这一篇写写复制错误处理相关的另两个参数slave_skip_errors、slave_exec_mode,基本环境参考《复制错误处理——sql_slave_skip_counter

一、slave_skip_errors

1.1、slave_skip_errors官方解释

https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html
--slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]
Normally, replication stops when an error occurs on the slave, which gives you the opportunity to resolve the inconsistency in the data manually. This option causes the slave SQL thread to continue replication when a statement returns any of the errors listed in the option value.
Do not use this option unless you fully understand why you are getting errors. If there are no bugs in your replication setup and client programs, and no bugs in MySQL itself, an error that stops replication should never occur. Indiscriminate use of this option results in slaves becoming hopelessly out of synchrony with the master, with you having no idea why this has occurred.

1.2、测试数据

slave_skip_errors是一个非Dynamic变量,在配置文件中添加

[mysqld]
slave_skip_errors=1032,1062
View Code

主库创建一个事务表和一个非事务表,然后从库往各表写入id=1的记录

# 主库创建测试表
mydba@192.168.85.132,3306 [replcrash]> create table repl_innodb(id int primary key,name1 char(10),name2 char(10)) engine=innodb;
mydba@192.168.85.132,3306 [replcrash]> create table repl_myisam(id int primary key,name1 char(10),name2 char(10)) engine=myisam;

# 从库往测试表中添加数据,不记入binlog
mydba@192.168.85.133,3306 [replcrash]> set sql_log_bin=0;
mydba@192.168.85.133,3306 [replcrash]> insert into repl_innodb(id,name1,name2) values(1,'s1062-1','s1062-1');
mydba@192.168.85.133,3306 [replcrash]> insert into repl_myisam(id,name1,name2) values(1,'s1062-1','s1062-1');
mydba@192.168.85.133,3306 [replcrash]> set sql_log_bin=1;
View Code

1.3、一个事务中包含事务表和非事务表操作

这里不再单独对事务表和非事务表进行测试

# 主库往事务表、非事务表中添加数据
mydba@192.168.85.132,3306 [replcrash]> begin;
mydba@192.168.85.132,3306 [replcrash]> insert into repl_innodb(id,name1,name2) values(1,'m1062-1','m1062-1');
mydba@192.168.85.132,3306 [replcrash]> insert into repl_innodb(id,name1,name2) values(2,'m1062-2','m1062-2');
mydba@192.168.85.132,3306 [replcrash]> insert into repl_myisam(id,name1,name2) values(1,'m1062-1','m1062-1');
mydba@192.168.85.132,3306 [replcrash]> insert into repl_myisam(id,name1,name2) values(2,'m1062-2','m1062-2');
mydba@192.168.85.132,3306 [replcrash]> commit;

# 主库数据
mydba@192.168.85.132,3306 [replcrash]> select * from repl_innodb;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | m1062-1 | m1062-1 |
|  2 | m1062-2 | m1062-2 |
+----+---------+---------+
mydba@192.168.85.132,3306 [replcrash]> select * from repl_myisam;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | m1062-1 | m1062-1 |
|  2 | m1062-2 | m1062-2 |
+----+---------+---------+

# 从库数据
mydba@192.168.85.133,3306 [replcrash]> select * from repl_innodb;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | s1062-1 | s1062-1 |
|  2 | m1062-2 | m1062-2 |
+----+---------+---------+
mydba@192.168.85.133,3306 [replcrash]> select * from repl_myisam;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | s1062-1 | s1062-1 |
|  2 | m1062-2 | m1062-2 |
+----+---------+---------+
View Code

复制正常,从库repl_myisam表跳过id=1的记录,复制了id=2的记录;从库repl_innodb表跳过id=1的记录,复制了id=2的记录
语句操作过程:开启显式事务1,往repl_innodb表写入id=1、2两条记录-->开启事务2,往repl_myisam表写入id=1记录,提交事务2-->开启事务3,往repl_myisam表写入id=2记录,提交事务3-->提交显式事务1
当事务2提交后,从库上repl_myisam.id=1的Duplicate entry被skip;当事务3提交后,从库写入repl_myisam.id=2的记录;当事务1提交后,从库上repl_innodb.id=1的Duplicate entry被skip,从库写入repl_innodb.id=2的记录~
也就是说配置文件中的slave_skip_errors=1032,1062 它仅跳过出错的行,并不是跳过整个事务(sql_slave_skip_counter会跳过整个事务)
试想,如果主库上的显式事务中有update操作,然后在从库找不到对应行,它仅跳过出错的行,主从不一致的情况将继续,并且不会触发错误

[root@ZST1 logs]# mysqlbinlog -v --base64-output=decode-rows mysql-bin.000008 --start-position=1333
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 1333
#171201 21:08:18 server id 1323306  end_log_pos 1398 CRC32 0xd792f990   Anonymous_GTID  last_committed=5        sequence_number=6       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1398
#171201 21:08:18 server id 1323306  end_log_pos 1475 CRC32 0x1869ed89   Query   thread_id=3     exec_time=0     error_code=0
SET TIMESTAMP=1512133698/*!*/;
SET @@session.pseudo_thread_id=3/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
==================== repl_myisam表写入id=1的记录Start ====================
BEGIN
/*!*/;
# at 1475
#171201 21:08:18 server id 1323306  end_log_pos 1540 CRC32 0x7f6a1e44   Table_map: `replcrash`.`repl_myisam` mapped to number 307
# at 1540
#171201 21:08:18 server id 1323306  end_log_pos 1596 CRC32 0xb6784f59   Write_rows: table id 307 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_myisam`
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 1596
#171201 21:08:18 server id 1323306  end_log_pos 1674 CRC32 0xdebe509f   Query   thread_id=3     exec_time=0     error_code=0
SET TIMESTAMP=1512133698/*!*/;
COMMIT
/*!*/;
# at 1674
==================== repl_myisam表写入id=1的记录End ====================
#171201 21:08:40 server id 1323306  end_log_pos 1739 CRC32 0x09f01ffa   Anonymous_GTID  last_committed=6        sequence_number=7       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1739
#171201 21:08:40 server id 1323306  end_log_pos 1816 CRC32 0x9b1cba09   Query   thread_id=3     exec_time=0     error_code=0
SET TIMESTAMP=1512133720/*!*/;
BEGIN
/*!*/;
# at 1816
#171201 21:08:40 server id 1323306  end_log_pos 1881 CRC32 0xf8e7ddd7   Table_map: `replcrash`.`repl_myisam` mapped to number 307
# at 1881
#171201 21:08:40 server id 1323306  end_log_pos 1937 CRC32 0xa2150d71   Write_rows: table id 307 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_myisam`
### SET
###   @1=2
###   @2='m1062-2'
###   @3='m1062-2'
# at 1937
#171201 21:08:40 server id 1323306  end_log_pos 2015 CRC32 0xb007bae6   Query   thread_id=3     exec_time=0     error_code=0
SET TIMESTAMP=1512133720/*!*/;
COMMIT
/*!*/;
# at 2015
==================== repl_myisam表写入id=2的记录End ====================
#171201 21:08:56 server id 1323306  end_log_pos 2080 CRC32 0x39e67db5   Anonymous_GTID  last_committed=7        sequence_number=8       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2080
#171201 21:07:59 server id 1323306  end_log_pos 2157 CRC32 0xb1ae59f2   Query   thread_id=3     exec_time=0     error_code=0
SET TIMESTAMP=1512133679/*!*/;
==================== repl_innodb表写入id=1、2的记录,在一个事务中Start ====================
BEGIN
/*!*/;
# at 2157
#171201 21:07:59 server id 1323306  end_log_pos 2222 CRC32 0x09d40a4f   Table_map: `replcrash`.`repl_innodb` mapped to number 306
# at 2222
#171201 21:07:59 server id 1323306  end_log_pos 2278 CRC32 0x834f2f78   Write_rows: table id 306 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_innodb`
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 2278
#171201 21:08:07 server id 1323306  end_log_pos 2343 CRC32 0x5b7e244b   Table_map: `replcrash`.`repl_innodb` mapped to number 306
# at 2343
#171201 21:08:07 server id 1323306  end_log_pos 2399 CRC32 0x965812b9   Write_rows: table id 306 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_innodb`
### SET
###   @1=2
###   @2='m1062-2'
###   @3='m1062-2'
# at 2399
#171201 21:08:56 server id 1323306  end_log_pos 2430 CRC32 0xbddc1af8   Xid = 1076
COMMIT/*!*/;
==================== repl_innodb表写入id=1、2的记录,在一个事务中End ====================
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@ZST1 logs]# 
View Binlog

注意:如果主库使用insert into repl_innodb(id,name1,name2) values(1,'m1062-1','m1062-1'),(2,'m1062-2','m1062-2');
复制正常,从库直接跳过整个事务,主上id=1、2记录不会插入到从库,这种写法id=1和id=2之间是没有position分隔(解析binlog可以看出)

二、slave_exec_mode

2.1、slave_exec_mode官方解释

https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html
SET GLOBAL slave_exec_mode = ['IDEMPOTENT'|'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.
For 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.

2.2、初始数据

注释配置文件中的slave_skip_errors,然后初始数据

# 主库数据
mydba@192.168.85.132,3306 [replcrash]> select * from repl_innodb;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  2 | m1032-2 | m1032-2 |
|  3 | m1032-3 | m1032-3 |
+----+---------+---------+
mydba@192.168.85.132,3306 [replcrash]> select * from repl_myisam;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  2 | m1032-2 | m1032-2 |
|  3 | m1032-3 | m1032-3 |
+----+---------+---------+

# 从库数据
mydba@192.168.85.133,3306 [replcrash]> select * from repl_innodb;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | s1062-1 | s1062-1 |
+----+---------+---------+
mydba@192.168.85.133,3306 [replcrash]> select * from repl_myisam;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | s1062-1 | s1062-1 |
+----+---------+---------+
View Code

这里只是为了模拟1062(insert遇到duplicate-key)、1032(delete/update遇到no-key-found)错误

2.3、一个事务中包含事务表和非事务表操作

这里不再单独对事务表和非事务表进行测试

# 主库开启事务,insertupdatedelete
mydba@192.168.85.132,3306 [replcrash]> begin;
mydba@192.168.85.132,3306 [replcrash]> insert into repl_innodb(id,name1,name2) values(1,'m1062-1','m1062-1');
mydba@192.168.85.132,3306 [replcrash]> update repl_innodb set name1='m1032-2upd' where id = 2;
mydba@192.168.85.132,3306 [replcrash]> delete from repl_innodb where id=3;
mydba@192.168.85.132,3306 [replcrash]> insert into repl_innodb(id,name1,name2) values(4,'m1062-4','m1062-4');
mydba@192.168.85.132,3306 [replcrash]> insert into repl_myisam(id,name1,name2) values(1,'m1062-1','m1062-1');
mydba@192.168.85.132,3306 [replcrash]> update repl_myisam set name1='m1032-2upd' where id = 2;
mydba@192.168.85.132,3306 [replcrash]> delete from repl_myisam where id=3;
mydba@192.168.85.132,3306 [replcrash]> insert into repl_myisam(id,name1,name2) values(4,'m1062-4','m1062-4');
mydba@192.168.85.132,3306 [replcrash]> commit;

# 主库数据
mydba@192.168.85.132,3306 [replcrash]> select * from repl_innodb;
+----+------------+---------+
| id | name1      | name2   |
+----+------------+---------+
|  1 | m1062-1    | m1062-1 |
|  2 | m1032-2upd | m1032-2 |
|  4 | m1062-4    | m1062-4 |
+----+------------+---------+
mydba@192.168.85.132,3306 [replcrash]> select * from repl_myisam;
+----+------------+---------+
| id | name1      | name2   |
+----+------------+---------+
|  1 | m1062-1    | m1062-1 |
|  2 | m1032-2upd | m1032-2 |
|  4 | m1062-4    | m1062-4 |
+----+------------+---------+
View Code

从库在应用insert into repl_myisam(id,name1,name2) values(1,'m1062-1','m1062-1')时,从库报错replcrash.repl_myisam; Duplicate entry '1',SQL thread停止。前面对repl_innodb的操作还没有commit,所以从库此时数据没有任何变化。尝试设置从库设置slave_exec_mode参数

# 从库设置slave_exec_mode='IDEMPOTENT'
mydba@192.168.85.133,3306 [(none)]> set global slave_exec_mode='IDEMPOTENT'; 
mydba@192.168.85.133,3306 [(none)]> start slave sql_thread;

# 从库数据
mydba@192.168.85.133,3306 [replcrash]> select * from repl_innodb;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | m1062-1 | m1062-1 |
|  4 | m1062-4 | m1062-4 |
+----+---------+---------+
mydba@192.168.85.133,3306 [replcrash]> select * from repl_myisam;
+----+---------+---------+
| id | name1   | name2   |
+----+---------+---------+
|  1 | m1062-1 | m1062-1 |
|  4 | m1062-4 | m1062-4 |
+----+---------+---------+
View Code

从库更新了id=1的记录,写入了id=4的记录,它是以什么顺序来执行的呢?我们先来查看主库上的binlog

[root@ZST1 logs]# mysqlbinlog -v --base64-output=decode-rows mysql-bin.000008 --start-position=2430
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 2430
#171201 23:01:19 server id 1323306  end_log_pos 2495 CRC32 0x99557a42   Anonymous_GTID  last_committed=8        sequence_number=9       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2495
#171201 23:01:19 server id 1323306  end_log_pos 2572 CRC32 0xdcd2d27f   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140479/*!*/;
SET @@session.pseudo_thread_id=13/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
==================== repl_myisam表写入id=1的记录Start ====================
BEGIN
/*!*/;
# at 2572
#171201 23:01:19 server id 1323306  end_log_pos 2637 CRC32 0x48b4dd17   Table_map: `replcrash`.`repl_myisam` mapped to number 309
# at 2637
#171201 23:01:19 server id 1323306  end_log_pos 2693 CRC32 0x8d519b60   Write_rows: table id 309 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_myisam`
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 2693
#171201 23:01:19 server id 1323306  end_log_pos 2771 CRC32 0xe0be0f09   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140479/*!*/;
COMMIT
/*!*/;
# at 2771
==================== repl_myisam表写入id=1的记录End ====================
#171201 23:01:36 server id 1323306  end_log_pos 2836 CRC32 0xfb8a1915   Anonymous_GTID  last_committed=9        sequence_number=10      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2836
#171201 23:01:36 server id 1323306  end_log_pos 2913 CRC32 0xf2abbe32   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140496/*!*/;
==================== repl_myisam表更新id=2的记录Start ====================
BEGIN
/*!*/;
# at 2913
#171201 23:01:36 server id 1323306  end_log_pos 2978 CRC32 0x2b4285a4   Table_map: `replcrash`.`repl_myisam` mapped to number 309
# at 2978
#171201 23:01:36 server id 1323306  end_log_pos 3059 CRC32 0x6f94f7cb   Update_rows: table id 309 flags: STMT_END_F
### UPDATE `replcrash`.`repl_myisam`
### WHERE
###   @1=2
###   @2='m1032-2'
###   @3='m1032-2'
### SET
###   @1=2
###   @2='m1032-2upd'
###   @3='m1032-2'
# at 3059
#171201 23:01:36 server id 1323306  end_log_pos 3137 CRC32 0x2a8e5489   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140496/*!*/;
COMMIT
/*!*/;
# at 3137
==================== repl_myisam表更新id=2的记录End ====================
#171201 23:01:45 server id 1323306  end_log_pos 3202 CRC32 0xc7ef1e5e   Anonymous_GTID  last_committed=10       sequence_number=11      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3202
#171201 23:01:45 server id 1323306  end_log_pos 3279 CRC32 0xcf5e63ac   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140505/*!*/;
==================== repl_myisam表删除id=3的记录Start ====================
BEGIN
/*!*/;
# at 3279
#171201 23:01:45 server id 1323306  end_log_pos 3344 CRC32 0xb6020c12   Table_map: `replcrash`.`repl_myisam` mapped to number 309
# at 3344
#171201 23:01:45 server id 1323306  end_log_pos 3400 CRC32 0x5fc1ee98   Delete_rows: table id 309 flags: STMT_END_F
### DELETE FROM `replcrash`.`repl_myisam`
### WHERE
###   @1=3
###   @2='m1032-3'
###   @3='m1032-3'
# at 3400
#171201 23:01:45 server id 1323306  end_log_pos 3478 CRC32 0x6aab62fd   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140505/*!*/;
COMMIT
/*!*/;
# at 3478
==================== repl_myisam表删除id=3的记录End ====================
#171201 23:01:52 server id 1323306  end_log_pos 3543 CRC32 0xed36610c   Anonymous_GTID  last_committed=11       sequence_number=12      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3543
#171201 23:01:52 server id 1323306  end_log_pos 3620 CRC32 0x5a134f60   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140512/*!*/;
==================== repl_myisam表写入id=4的记录Start ====================
BEGIN
/*!*/;
# at 3620
#171201 23:01:52 server id 1323306  end_log_pos 3685 CRC32 0x317d7f86   Table_map: `replcrash`.`repl_myisam` mapped to number 309
# at 3685
#171201 23:01:52 server id 1323306  end_log_pos 3741 CRC32 0x50f84020   Write_rows: table id 309 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_myisam`
### SET
###   @1=4
###   @2='m1062-4'
###   @3='m1062-4'
# at 3741
#171201 23:01:52 server id 1323306  end_log_pos 3819 CRC32 0xdc200995   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140512/*!*/;
COMMIT
/*!*/;
# at 3819
==================== repl_myisam表写入id=4的记录End ====================
#171201 23:01:58 server id 1323306  end_log_pos 3884 CRC32 0xaae63436   Anonymous_GTID  last_committed=12       sequence_number=13      rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3884
#171201 23:00:04 server id 1323306  end_log_pos 3961 CRC32 0xb14f2893   Query   thread_id=13    exec_time=0     error_code=0
SET TIMESTAMP=1512140404/*!*/;
==================== repl_innodb表操作id=123、4的记录,在一个事务中Start ====================
BEGIN
/*!*/;
# at 3961
#171201 23:00:04 server id 1323306  end_log_pos 4026 CRC32 0x62020112   Table_map: `replcrash`.`repl_innodb` mapped to number 308
# at 4026
#171201 23:00:04 server id 1323306  end_log_pos 4082 CRC32 0xa6c81e06   Write_rows: table id 308 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_innodb`
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 4082
#171201 23:00:14 server id 1323306  end_log_pos 4147 CRC32 0x0a4abc3c   Table_map: `replcrash`.`repl_innodb` mapped to number 308
# at 4147
#171201 23:00:14 server id 1323306  end_log_pos 4228 CRC32 0xdcd94aa2   Update_rows: table id 308 flags: STMT_END_F
### UPDATE `replcrash`.`repl_innodb`
### WHERE
###   @1=2
###   @2='m1032-2'
###   @3='m1032-2'
### SET
###   @1=2
###   @2='m1032-2upd'
###   @3='m1032-2'
# at 4228
#171201 23:00:22 server id 1323306  end_log_pos 4293 CRC32 0xf5a4c9ba   Table_map: `replcrash`.`repl_innodb` mapped to number 308
# at 4293
#171201 23:00:22 server id 1323306  end_log_pos 4349 CRC32 0xbd1864f7   Delete_rows: table id 308 flags: STMT_END_F
### DELETE FROM `replcrash`.`repl_innodb`
### WHERE
###   @1=3
###   @2='m1032-3'
###   @3='m1032-3'
# at 4349
#171201 23:00:32 server id 1323306  end_log_pos 4414 CRC32 0x89bcb330   Table_map: `replcrash`.`repl_innodb` mapped to number 308
# at 4414
#171201 23:00:32 server id 1323306  end_log_pos 4470 CRC32 0x80d6ed1a   Write_rows: table id 308 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_innodb`
### SET
###   @1=4
###   @2='m1062-4'
###   @3='m1062-4'
# at 4470
#171201 23:01:58 server id 1323306  end_log_pos 4501 CRC32 0xdc2e8ab8   Xid = 1133
COMMIT/*!*/;
==================== repl_innodb表操作id=123、4的记录,在一个事务中Start ====================
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@ZST1 logs]# 
Master Binlog

语句操作过程:开启显式事务1,往repl_innodb表操作id=1(ins)、2(upd)、3(del)、4(ins)的记录-->开启事务2,往repl_myisam表写入id=1的记录,提交事务2-->开启事务3,更新repl_myisam表id=2的记录,提交事务3-->开启事务4,删除repl_myisam表id=3的记录,提交事务4-->开启事务5,往repl_myisam表写入id=4的记录,提交事务5-->提交显式事务1
binlog中我们可以看出,是按commit顺序,先记录repl_myisam的操作,然后记录repl_innodb的操作^_-
我们再来查看从库上的binlog

[root@ZST2 logs]# mysqlbinlog -v --base64-output=decode-rows mysql-bin.000003
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#171201 22:54:07 server id 1333306  end_log_pos 123 CRC32 0xb5872a85    Start: binlog v 4, server v 5.7.19-log created 171201 22:54:07 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
# at 123
#171201 22:54:08 server id 1333306  end_log_pos 154 CRC32 0x2f0d74be    Previous-GTIDs
# [empty]
# at 154
#171201 23:01:19 server id 1323306  end_log_pos 219 CRC32 0x227de897    Anonymous_GTID  last_committed=0        sequence_number=1       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#171201 23:01:19 server id 1323306  end_log_pos 282 CRC32 0x9bd4c099    Query   thread_id=13    exec_time=322   error_code=0
SET TIMESTAMP=1512140479/*!*/;
SET @@session.pseudo_thread_id=13/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=524288/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
==================== repl_myisam表写入id=1的记录,重复key进行update操作,Start ====================
BEGIN
/*!*/;
# at 282
#171201 23:01:19 server id 1323306  end_log_pos 347 CRC32 0xe221b9d8    Table_map: `replcrash`.`repl_myisam` mapped to number 124
# at 347
#171201 23:01:19 server id 1323306  end_log_pos 425 CRC32 0x32dc6ddc    Update_rows: table id 124 flags: STMT_END_F
### UPDATE `replcrash`.`repl_myisam`
### WHERE
###   @1=1
###   @2='s1062-1'
###   @3='s1062-1'
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 425
#171201 23:01:19 server id 1323306  end_log_pos 489 CRC32 0x8e56c4de    Query   thread_id=13    exec_time=322   error_code=0
SET TIMESTAMP=1512140479/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
COMMIT
/*!*/;
# at 489
==================== repl_myisam表写入id=1的记录,重复key进行update操作,End ====================

==================== repl_myisam表更新id=2、删除id=3的记录Start ====================
update/delete 在从库没找到记录,没有做任何处理,相当于skip
==================== repl_myisam表更新id=2、删除id=3的记录End ====================

#171201 23:01:52 server id 1323306  end_log_pos 554 CRC32 0x0401a98f    Anonymous_GTID  last_committed=1        sequence_number=2       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 554
#171201 23:01:52 server id 1323306  end_log_pos 617 CRC32 0xb8743fdf    Query   thread_id=13    exec_time=289   error_code=0
SET TIMESTAMP=1512140512/*!*/;
SET @@session.sql_mode=524288/*!*/;
==================== repl_myisam表写入id=4的记录Start ====================
BEGIN
/*!*/;
# at 617
#171201 23:01:52 server id 1323306  end_log_pos 682 CRC32 0x8dc365d7    Table_map: `replcrash`.`repl_myisam` mapped to number 124
# at 682
#171201 23:01:52 server id 1323306  end_log_pos 738 CRC32 0x773e7fc0    Write_rows: table id 124 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_myisam`
### SET
###   @1=4
###   @2='m1062-4'
###   @3='m1062-4'
# at 738
#171201 23:01:52 server id 1323306  end_log_pos 802 CRC32 0x221bf96b    Query   thread_id=13    exec_time=289   error_code=0
SET TIMESTAMP=1512140512/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
COMMIT
/*!*/;
# at 802
==================== repl_myisam表写入id=4的记录End ====================
#171201 23:00:32 server id 1323306  end_log_pos 867 CRC32 0x4e47e1fc    Anonymous_GTID  last_committed=2        sequence_number=3       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 867
#171201 23:00:04 server id 1323306  end_log_pos 930 CRC32 0x081b8094    Query   thread_id=13    exec_time=397   error_code=0
SET TIMESTAMP=1512140404/*!*/;
SET @@session.sql_mode=524288/*!*/;
==================== repl_innodb表操作id=1、4的记录(2、3被skip),在一个事务中Start ====================
BEGIN
/*!*/;
# at 930
#171201 23:00:04 server id 1323306  end_log_pos 995 CRC32 0x9797a0bd    Table_map: `replcrash`.`repl_innodb` mapped to number 123
# at 995
#171201 23:00:04 server id 1323306  end_log_pos 1073 CRC32 0xe457ab20   Update_rows: table id 123 flags: STMT_END_F
### UPDATE `replcrash`.`repl_innodb`
### WHERE
###   @1=1
###   @2='s1062-1'
###   @3='s1062-1'
### SET
###   @1=1
###   @2='m1062-1'
###   @3='m1062-1'
# at 1073
#171201 23:00:32 server id 1323306  end_log_pos 1138 CRC32 0x6fd579ab   Table_map: `replcrash`.`repl_innodb` mapped to number 123
# at 1138
#171201 23:00:32 server id 1323306  end_log_pos 1194 CRC32 0x6c5678ef   Write_rows: table id 123 flags: STMT_END_F
### INSERT INTO `replcrash`.`repl_innodb`
### SET
###   @1=4
###   @2='m1062-4'
###   @3='m1062-4'
# at 1194
#171201 23:00:32 server id 1323306  end_log_pos 1225 CRC32 0x594d2812   Xid = 45
COMMIT/*!*/;
==================== repl_innodb表操作id=1、4的记录(2、3被skip),在一个事务中End ====================
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@ZST2 logs]# 
Slave Binlog

它也是按照主库的binlog的顺序,先提交repl_myisam操作,再提交repl_innodb操作。对于insert在从库有重复记录的,从库update为主库的值;对于update/delete在从库没找到记录的,不做任何处理,相当于skip~
When slave_exec_mode is IDEMPOTENT, a failure to apply changes from RBL(Row-Based Logging) because the original row cannot be found does not trigger an error or cause replication to fail. This means that it is possible that updates are not applied on the slave, so that the master and slave are no longer synchronized. Latency issues and use of nontransactional tables with RBR(Statement-Based Logging) when slave_exec_mode is IDEMPOTENT can cause the master and slave to diverge even further.

三、总结

正常情况下,应该是从库遇到错误就停止复制,然后人工去处理数据一致性问题。slave-skip-errors选项会导致SQL thread遇到配置中的错误后继续复制。滥用slave-skip-errors会在你全然不知的情况下导致主从数据不一致。
slave_exec_mode='IDEMPOTENT',适合多主、循环、以及其他特殊复制场景。RBL(Row-Based Logging)环境下也会出现SBL(Statement-Based Logging)场景中主从数据不一致,复制状态正常
遇到复制中断第一时间要想怎么满足这个复制,而不是去跳过这个事务(・ω・)

转载于:https://www.cnblogs.com/Uest/p/7943932.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a86793222/article/details/101606040

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签