MySQL复制跳过错误--slave_skip_errors、sql_slave_skip_counter、slave_exec_mode
MySQL主從復制中的跳過錯誤處理參數--slave_skip_errors、sql_slave_skip_counter、slave_exec_mode
跳過復制錯誤——slave_skip_errors、slave_exec_mode
跳過復制錯誤——sql_slave_skip_counter
1 簡介
? ? mysql在主從復制過程中,由于各種的原因,從服務器可能會遇到執行BINLOG中的SQL出錯的情況,在默認情況下,服務器會停止復制進程,不再進行同步,等到用戶自行來處理。
? ? slave-skip-errors的作用就是用來定義復制過程中從服務器可以自動跳過的錯誤號,當復制過程中遇到定義的錯誤號,就可以自動跳過,直接執行后面的SQL語句。
2 官方參考
? ? 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
?my.cnf中的寫法:
slave_skip_errors=1062,1053??
slave_skip_errors=all??
slave_skip_errors=ddl_exist_errors??
??
? 作為mysql啟動參數的寫法:
--slave-skip-errors=1062,1053??
--slave-skip-errors=all??
--slave-skip-errors=ddl_exist_errors??
? ??
從數據庫中查看該參數的值:
mysql> show variables like 'slave_skip%';??
+-------------------+-------+??
| Variable_name? ? ?| Value |??
+-------------------+-------+??
| slave_skip_errors | 1007? |??
+-------------------+-------+??
3 舉例分析
? ? 3.1 測試說明
? ? 配置好mysql主從同步,然后在從上寫入數據,造成主從不一致。
? ? 3.2 準備測試表結構
? ? 在主機上創建表:
create table replication (c1 int not null primary key, c2 varchar(10));??
? ? 3.3 準備測試數據
? ? 在主機上插入基礎數據
mysql> insert into replication values (1, 'test1');??
mysql> insert into replication values (2, 'test2');??
? ? 此時,主機從機replication表里面都有兩條記錄
? ? 3.4 開始測試
? ? 從機插入一條記錄
mysql> insert into replication values (3, 'test3');??
? ? 然后在主機上執行相同的操作
mysql> insert into replication values (3, 'test3');??
? ? 在從機上查看復制狀態
mysql> show slave status \G??
*************************** 1. row ***************************??
? ? ? ? ? ? ? ?Slave_IO_State: Waiting for master to send event??
? ? ? ? ? ? ? ? ? Master_Host: 192.168.1.222??
? ? ? ? ? ? ? ? ? Master_User: repl??
? ? ? ? ? ? ? ? ? Master_Port: 3306??
? ? ? ? ? ? ? ? Connect_Retry: 60??
? ? ? ? ? ? ? Master_Log_File: mysql-bin.000003??
? ? ? ? ? Read_Master_Log_Pos: 16700??
? ? ? ? ? ? ? ?Relay_Log_File: mysql-relay-bin.000003??
? ? ? ? ? ? ? ? Relay_Log_Pos: 16595??
? ? ? ? Relay_Master_Log_File: mysql-bin.000003??
? ? ? ? ? ? ?Slave_IO_Running: Yes??
? ? ? ? ? ? Slave_SQL_Running: No??
? ? ? ? ? ? ? Replicate_Do_DB:? ?
? ? ? ? ? Replicate_Ignore_DB:? ?
? ? ? ? ? ?Replicate_Do_Table:? ?
? ? ? ?Replicate_Ignore_Table: mysql.ibbackup_binlog_marker??
? ? ? Replicate_Wild_Do_Table:? ?
? Replicate_Wild_Ignore_Table: mysql.backup_%??
? ? ? ? ? ? ? ? ? ?Last_Errno: 1062??
? ? ? ? ? ? ? ? ? ?Last_Error: Error 'Duplicate entry '3' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'insert into replication values (3, 'test3')'??
? ? ? ? ? ? ? ? ?Skip_Counter: 0??
? ? ? ? ? Exec_Master_Log_Pos: 16425??
? ? ? ? ? ? ? Relay_Log_Space: 17544??
? ? 可以看到:sql線程已經停止工作 Slave_SQL_Running: No
? ? ? ? ? ? ? ? ? ? ? ? 錯誤號為:Last_Errno: 1062
? ? ? ? ? ? ? ? ? ? ? ? 錯誤信息為:Last_Error: Error 'Duplicate entry '3' for key 'PRIMARY'' on query. Default database: 'test'. Query: 'insert into replication values (3, 'test3')'
? ? 如果我們在my.cnf中加入如下選項,則可跳過此錯誤,數據同步繼續進行。
[mysqld]??
slave_skip_errors=1062??
? ? 具體測試方法同上,大家可自己驗證。
4 從backup恢復時從機復制出錯的一些解釋
? ? mysql企業版備份工具meb提供在線熱備功能,如果在備份過程中執行ddl操作,從機需要從主機的備份恢復時可能會異常,從而導致從機同步數據失敗。原因是從機恢復時需要先從備份文件恢復(包含備份過程中執行的ddl語句),
同步時不是從全備后的最后一個位置同步,而是從ddl的上個位置同步,如果再次執行該ddl語句在從機上不會造成沖突,
則同步繼續,如果會造成沖突,同步終止。解決此沖突的辦法是在my.cnf文件中加入一行
[mysqld]??
slave_skip_errors=ddl_exist_errors??
5 注意事項
? ? 5.1 該參數為全局靜態參數,不能動態調整,可在my.cnf中加入該參數列表后重啟mysql服務器生效。
? ? 5.2 必須注意的是,啟動這個參數,如果處理不當,很可能造成主從數據庫的數據不同步,在應用中需要根據實際情況,如果對數據完整性要求不是很嚴格,那么這個選項確實可以減輕維護的成本
****************************************************************************************
sql_slave_skip_counter 介紹:
摘自MySQL官方的解釋( 強烈建議閱讀英文原文 。中文版,是筆者自己的理解,只能說仁者見仁)
SET GLOBAL sql_slave_skip_counter Syntax:
??????? SET GLOBAL sql_slave_skip_counter = N
This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.
??????? 跳過N個events。注意:以event為單位,而不是以事務為單位,只有在由單條語句組成的事務時,兩者才等價。
??????? 如:一個事務由多個EVENT組成,BEGIN;INSERT;UPDATE;DELETE;COMMOIT; 這種情況下,兩者絕不相等
This statement is valid only when the slave threads are not running. Otherwise, it produces an error.
When using this statement, it is important to understand that the binary log is actually organized as a sequence of groups known as event groups. Each event group consists of a sequence of events.
For transactional tables, an event group corresponds to a transaction.
??? ????對于事務表,一個event group對應一個事務
or nontransactional tables, an event group corresponds to a single SQL statement.?
??????? 對于非事務表,一個event group對應一條SQL
When you use SET GLOBAL sql_slave_skip_counter to skip events and the result is in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group
??? ????當你跳過event的時候,如果N的值,處于event group之中,那么slave會繼續跳過event,直至跳過這個event group,從下一個event group開始
對于事務表使用 sql_slave_skip_counter 的情況:
1、跳過1032復制錯誤(update/delete error)
跳過由單條SQL組成的事務:
在Slave主機上人為的刪除兩條數據:
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '9';?
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '11';?
而Master在變更上述兩條記錄的時候會報錯,導致復制中斷:
INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('孫權', '吳國', '妹妹');?
UPDATE `edusoho_e`.`t1` SET xname='游戲' WHERE id=7;
UPDATE `edusoho_e`.`t1` SET age=40 WHERE id=11;???? #報錯
DELETE FROM `edusoho_e`.`t1` WHERE age=40;??????????? ?#報錯
INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('曹丕', '魏國', '甄姬');
DELETE FROM `edusoho_e`.`t1` WHERE id=1;
UPDATE `edusoho_e`.`t1` SET hobby='Games' WHERE id=3;?
在Slave查看主從復制狀態時,就會發現報錯信息:
mysql> show slave status\G;
*************************** 1. row ***************************
Read_Master_Log_Pos: 2176
Exec_Master_Log_Pos:? 874
Last_Errno: 1032
Last_Error: Could not execute? Update_rows ?event on table edusoho_e.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000002, end_log_pos 1127
Slave_IO_Running: Yes
Slave_SQL_Running: No
在Master主機上查看position做了什么操作:
mysql> show binlog events in 'mysql-bin.000002' from 874;
+------------------+------+-------------+-----------+-------------+---------------------------------+
| Log_name???????? | Pos? | Event_type? | Server_id | End_log_pos | Info??????????????????????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------+
| mysql-bin.000002 |?? 874? | Query?????? |???????? 2 |???????? 956 | BEGIN?????????????????????????? |
| mysql-bin.000002 |? 956 | Table_map?? |???????? 2 |??????? 1017 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 1017 | Update_rows |???????? 2 |??????? 1127 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 1127 | Xid???????? |???????? 2 |??????? 1158 | COMMIT /* xid=437 */??????????? |
| mysql-bin.000002 | 1158 | Query?????? |???????? 2 |??????? 1240 | BEGIN?????????????????????????? |
| mysql-bin.000002 | 1240 | Table_map?? |???????? 2 |??????? 1301 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 1301 | Delete_rows |???????? 2 |??????? 1407 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 1407 | Xid???????? |???????? 2 |??????? 1438 | COMMIT /* xid=446 */??????????? |
| mysql-bin.000002 | 1438 | Query?????? |???????? 2 |??????? 1520 | BEGIN?????????????????????????? |
| mysql-bin.000002 | 1520 | Table_map?? |???????? 2 |??????? 1581 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 1581 | Write_rows? |???????? 2 |??????? 1644 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 1644 | Xid???????? |???????? 2 |??????? 1675 | COMMIT /* xid=455 */??????????? |
| mysql-bin.000002 | 1675 | Query?????? |???????? 2 |??????? 1757 | BEGIN?????????????????????????? |
| mysql-bin.000002 | 1757 | Table_map?? |???????? 2 |??????? 1818 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 1818 | Delete_rows |???????? 2 |??????? 1880 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 1880 | Xid???????? |???????? 2 |??????? 1911 | COMMIT /* xid=464 */??????????? |
| mysql-bin.000002 | 1911 | Query?????? |???????? 2 |??????? 1993 | BEGIN?????????????????????????? |
| mysql-bin.000002 | 1993 | Table_map?? |???????? 2 |??????? 2054 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 2054 | Update_rows |???????? 2 |??????? 2145 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 2145 | Xid???????? |???????? 2 |??????? 2176 | COMMIT /* xid=473 */??????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------+
在Slave跳過第一個 Update_rows event 復制報錯:
mysql>? set global sql_slave_skip_counter=1;
mysql> ?start slave sql_thread;
mysql> show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: No
Exec_Master_Log_Pos:? 1158
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute? Delete_rows ?event on table edusoho_e.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000002, end_log_pos 1407
成功跳過第一個events group
在Slave繼續跳過第二個 Delete_rows event 復制報錯:
mysql> set global sql_slave_skip_counter=1;
mysql> start slave sql_thread;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_SQL_Errno: 0
Last_SQL_Error:?
成功跳過第二個 events group
注意:
雖然主從復制出現的故障成功跳過了,但只是暫時恢復了正常的主從復制狀態,需要盡快的對Slave缺失的數據進行補齊,不然Master對Slave不存在的數據做的變更,仍然會重復導致主從復制故障,筆者覺得如果你的數據量差異不是太大的話,可以考慮使用 pt-table-checksum 和 pt-table-sync 工具進行恢復,如果你的數據量很大且數據差異很多,還是建議重做Slave較好,因為使用工具會鎖表,會對線上業務造成一定的影響,具體情況,請自行考量。
跳過由多條SQL(event)組成的事務:
在Slave主機上人為的刪除一條數據:
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '7';?
在Master主機上產生一個由多條SQL組成的事務:
BEGIN;
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '7';?
INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('懶死', '不知道', '吃了睡睡了吃');?
COMMIT;
因為Slave主機上已經刪除id=7的數據,在Slave查看主從復制狀態時,就會發現報錯信息:
mysql> show slave status\G;
*************************** 1. row ***************************
Read_Master_Log_Pos: 7219
Exec_Master_Log_Pos:? 6840
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1032
Last_Error: Could not execute? Delete_rows ?event on table edusoho_e.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000002, end_log_pos 7049
在Master主機上查看position做了什么操作:
mysql> show binlog events in 'mysql-bin.000002' from 6840;
+------------------+------+-------------+-----------+-------------+---------------------------------+
| Log_name???????? | Pos? | Event_type? | Server_id | End_log_pos | Info??????????????????????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------+
| mysql-bin.000002 | 6840 | Query?????? |???????? 2 |??????? 6922 |? BEGIN??????????????????????????? |
| mysql-bin.000002 | 6922 | Table_map?? |???????? 2 |??????? 6983 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 6983 | Delete_rows |???????? 2 |??????? 7049 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 7049 | Table_map?? |???????? 2 |??????? 7110 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 7110 | Write_rows? |???????? 2 |??????? 7188 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 7188 | Xid???????? |???????? 2 |???????? 7219? |? COMMIT? /* xid=825 */??????????? |
+------------------+------+-------------+-----------+-------------+---------------------------------+
可以看到,這個事務是由兩個SQL(event)組成的
如果使用 sql_slave_skip_counter=N 跳過由多條SQL組成的事務會怎樣呢?
mysql> set global sql_slave_skip_counter=1;
mysql> start slave sql_thread;
mysql> show slave status\G;
*************************** 1. row ***************************
Read_Master_Log_Pos: 7219
Exec_Master_Log_Pos:? 7219
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_Errno: 0
Last_Error:
發現問題沒有 ,在使用sql_slave_skip_counter跳過由多條SQL(event)組成的事務時,從在Master上執行的 show binlog events 可以看到,如果只是跳過出報錯SQL語句,那么 Exec_Master_Log_Pos 值應該為7110,但是現在為7219,說明將整個event group跳過了,但是7110的SQL數據是我們需要的,所以,和單條SQL組成的事務一樣,主從復制狀態雖然恢復,但是數據仍處于不一致狀態,要抓緊時間補齊數據或重做Slave
2、 由多條SQL(event)組成的事務時,僅跳過一個event,而不是一個event group:
在Slave主機上人為的刪除一條數據:
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '17';?
在Master主機上產生一個由多條SQL組成的事務:
BEGIN;
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '17';
INSERT INTO `edusoho_e`.`t1` (`xname`, `address`, `hobby`) VALUES ('我是誰', '不知道', '吃了睡睡了吃');
COMMIT;
因為Slave主機上已經刪除id=17的數據,在Slave查看主從復制狀態時,就會發現報錯信息:
Exec_Master_Log_Pos:? 120
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1032
Last_Error: Could not execute? Delete_rows ?event on table edusoho_e.t1; Can't find record in 't1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000004, end_log_pos 341
在Master主機上查看position做了什么操作:
mysqlbinlog -v --base64-output=decode --start-position=120 mysql-bin.000004
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 120
#190507 13:52:05 server id 2? end_log_pos 202 CRC32 0x0ca0c280 ?? ?Query?? ?thread_id=3?? ?exec_time=0?? ?error_code=0
SET TIMESTAMP=1557208325/*!*/;
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=1073741824/*!*/;
SET @@session.auto_increment_increment=2, @@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/*!*/;
BEGIN
/*!*/;
# at 202
#190507 13:52:05 server id 2? end_log_pos 263 CRC32 0x20d2e89d ?? ?Table_map: `edusoho_e`.`t1` mapped to number 216
# at 263
#190507 13:52:05 server id 2? end_log_pos 341 CRC32 0xbec6fd45 ?? ?Delete_rows: table id 216 flags: STMT_END_F
### DELETE FROM `edusoho_e`.`t1`
### WHERE
###?? @1=17
###?? @2='懶死'
###?? @3='不知道'
###?? @4=1
###?? @5='吃了睡睡了吃'
###?? @6=18
# at 341
#190507 13:52:05 server id 2? end_log_pos 402 CRC32 0xa37bc5c9 ?? ?Table_map: `edusoho_e`.`t1` mapped to number 216
# at 402
#190507 13:52:05 server id 2? end_log_pos 483 CRC32 0x0d774707 ?? ?Write_rows: table id 216 flags: STMT_END_F
### INSERT INTO `edusoho_e`.`t1`
### SET
###?? @1=21
###?? @2='我是誰'
###?? @3='不知道'
###?? @4=1
###?? @5='吃了睡睡了吃'
###?? @6=18
# at 483
#190507 13:52:05 server id 2? end_log_pos 514 CRC32 0x8c333b30 ?? ?Xid = 411
COMMIT /*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
可以看到,綠色的部分就是我們需要跳過的,而第二個event是需要我們保留的
這個時候,就需要用到 slave_exec_mode 這個變量了,至于slave_exec_mode詳細介紹,還是請參考MySQL官網資料
mysql> set global slave_exec_mode='IDEMPOTENT';
mysql> start slave sql_thread;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Exec_Master_Log_Pos: 514
去Slave上edusoho_e.t1表上查看,數據id=21的數據已經過去了,此時,數據處于一致性狀態
3、 跳過主鍵沖突1062錯誤(Duplicate entry):
在Slave主鍵上先插入一條id值:
INSERT INTO `edusoho_e`.`t1` (`id`,`xname`, `address`, `hobby`, `age`) VALUES (19,'小玩子', '明朝', '皇后', '25');?
因為Slave已經占用了Master要自動產生的主鍵值id=19,所以Slave主機會報錯:
INSERT INTO `edusoho_e`.`t1` (`id`,`xname`, `address`, `hobby`, `age`) VALUES (19,'朱棣', '明朝', '皇帝', '36');?
查看Slave主從復制狀態發現已經發生了主從復制報錯:
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table edusoho_e.t1;? Duplicate entry ?'19' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000002, end_log_pos 7425
Exec_Master_Log_Pos:? 7219
查看Master binlog:
mysql> show binlog events in 'mysql-bin.000002' from 7219;
+------------------+------+------------+-----------+-------------+---------------------------------+
| Log_name???????? | Pos? | Event_type | Server_id | End_log_pos | Info??????????????????????????? |
+------------------+------+------------+-----------+-------------+---------------------------------+
| mysql-bin.000002 | 7219 | Query????? |???????? 2 |??????? 7301 | BEGIN?????????????????????????? |
| mysql-bin.000002 | 7301 | Table_map? |???????? 2 |??????? 7362 | table_id: 213 (edusoho_e.t1)??? |
| mysql-bin.000002 | 7362 | Write_rows |???????? 2 |??????? 7425 | table_id: 213 flags: STMT_END_F |
| mysql-bin.000002 | 7425 | Xid??????? |???????? 2 |??????? 7456 | COMMIT /* xid=893 */??????????? |
+------------------+------+------------+-----------+-------------+---------------------------------+
思考:
因為Slave這條數據已經存在,如果在Slave主機上把這條數據刪除了,Slave會不會直接同步過來?(答案是:不會。需要重啟Slave thread):
DELETE FROM `edusoho_e`.`t1` WHERE `id` = '19';?
mysql> stop slave;
mysql> start slave user='repliter' password='123456';
驗證的時候,發現數據已經同步過去了
題外:
以上是筆者對于單條SQL組成的事務、多條SQL組成的事務,及在這些單/多條SQL組成的事務下,人為設置的1032和1062復制錯誤和解決方法,還有sql_slave_skip_counter和slave_exec_mode各自的用法和跳過的范圍,當然了, 筆者呢,做的只是線上應用前的部署測試,并沒有經過任何的實戰檢測。一方面,僅為廣大同行做個參考;另一方面,記錄筆者自己的心得和針對問題解決的思路做個總結,當問題真正發生的時候,有個方向可以進行參考,而不至于手忙腳亂,不知所措,所以,對其中有誤之處和理解不到位的地方,望請下方留言指正,不勝感激!
還有,筆者做的,只是針對事務表,做的 sql_slave_skip_counter和slave_exec_mode測試,對于非事務表, sql_slave_skip_counter和slave_exec_mode用途會稍有不同,請自行百度吧。
slave_exec_mode=IDEMPOTENT?在MySQL復制環境中是個很有用的參數:只要在備機運行set?global?slave_exec_mode=IDEMPOTENT?,備機的sql?thread就運行在冥等模式下,可以讓備機在insert主鍵、唯一鍵沖突,update、delete值未找到錯誤發生時不斷開復制而保持冥等性(當即生效,連slave的sql線程都不用重啟喲);而類似sql_slave_skip_counter=N和slave-skip-errors?=?N?這樣的粗暴跳過錯誤方法可能破壞主備一致性。但官方文檔的描述很簡潔,我一直好奇slave_exec_mode=IDEMPOTENT?是如何在復制出錯時保持一致性的--譬如主鍵沖突時是簡單跳過還是覆寫,今天在Percona?5.7下做了個實驗(binlog是row格式),實驗過程就省略了,直接總結如下: 1.insert場景 此時insert?into語句在備機的效果就跟replace?into一樣,但卻并不是把insert?into轉換成replace?into來執行,分兩種情況: a.MySQL配置成autocommit,直接一條insert?into?... 如這樣的insert insert?into?test?set?c1='a',c2='b'; 此時insert?into語句在備機執行時假如遇到主鍵沖突就先轉化為delete再insert delete?from?test?where?c1='old_value'?and?c2='old_value';??? insert?into?test?set?c1='a',c2='b';??? 假如遇到非主鍵的唯一鍵沖突就轉換為update update?test?set?set?c1='a',c2='b'?where?c1='old_value'?and?c2='old_value'; b.當顯示開始事務時(begin...insert?into...commit;) 如這樣的sql begin;??? ......? insert?into?test?set?c1='a',c2='b';??? ......? commit;??? 此時begin...commit里的insert?into語句在備機執行時假如遇到主鍵沖突、唯一鍵沖突都是先轉化為delete再insert begin;??? ......? delete?from?test?where?c1='old_value'?and?c2='old_value';??? insert?into?test?set?c1='a',c2='b';??? ......? commit;??? 2.update場景 當備機不存在要更新的記錄,這條update跳過不執行 3.delete場景? 同update場景一樣,備機跳過此delete啥也不干 注意:使用冥等模式時表要有主鍵 冥等模式并不是萬能的,除了不能對DDL操作冥等,對字段長度不同導致的錯誤也不是冥等(譬如主機一個字段是char(20)而備機是char(10)),還有一個限制就是表有主鍵才會對insert的冥等設置有效:因為insert的冥等行為是通過主鍵來判斷備機是否有重復值從而產生覆寫操作,如果表沒有主鍵,則備機即使設了冥等也可能會比主機多重復數據。
About Me
| ........................................................................................................................ ● 本文作者:小麥苗,部分內容整理自網絡,若有侵權請聯系小麥苗刪除 ● 本文在itpub、博客園、CSDN和個人微 信公眾號( xiaomaimiaolhr )上有同步更新 ● 本文itpub地址: http://blog.itpub.net/26736162 ● 本文博客園地址: http://www.cnblogs.com/lhrbest ● 本文CSDN地址: https://blog.csdn.net/lihuarongaini ● 本文pdf版、個人簡介及小麥苗云盤地址: http://blog.itpub.net/26736162/viewspace-1624453/ ● 數據庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/ ● DBA寶典今日頭條號地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826 ........................................................................................................................ ● QQ群號: 230161599 (滿) 、618766405 ● 微 信群:可加我微 信,我拉大家進群,非誠勿擾 ● 聯系我請加QQ好友 ( 646634621 ) ,注明添加緣由 ● 于 2019-07-01 06:00 ~ 2019-07-31 24:00 在西安完成 ● 最新修改時間:2019-07-01 06:00 ~ 2019-07-31 24:00 ● 文章內容來源于小麥苗的學習筆記,部分整理自網絡,若有侵權或不當之處還請諒解 ● 版權所有,歡迎分享本文,轉載請保留出處 ........................................................................................................................ ● 小麥苗的微店 : https://weidian.com/s/793741433?wfr=c&ifr=shopdetail ● 小麥苗出版的數據庫類叢書 : http://blog.itpub.net/26736162/viewspace-2142121/ ● 小麥苗OCP、OCM、高可用網絡班 : http://blog.itpub.net/26736162/viewspace-2148098/ ● 小麥苗騰訊課堂主頁 : https://lhr.ke.qq.com/ ........................................................................................................................ 使用 微 信客戶端 掃描下面的二維碼來關注小麥苗的微 信公眾號( xiaomaimiaolhr )及QQ群(DBA寶典)、添加小麥苗微 信, 學習最實用的數據庫技術。
........................................................................................................................ |
?
?
來自 “ ITPUB博客 ” ,鏈接:http://blog.itpub.net/26736162/viewspace-2651331/,如需轉載,請注明出處,否則將追究法律責任。
總結
以上是生活随笔為你收集整理的MySQL复制跳过错误--slave_skip_errors、sql_slave_skip_counter、slave_exec_mode的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 3613 Best Reward
- 下一篇: w ndows7管理员密码,Window