MySQL GTID 錯誤處理匯總

MySQL GTID是在傳統的mysql主從復制的基礎之上演化而來的產物,即通過UUID加上事務ID的方式來確保每一個事物的唯一性。這樣的操作方式使得我們不再需要關心所謂的log_file和log_Pos,只是簡單的告訴從庫,從哪個服務器上去找主庫就OK了。簡化了主從的搭建以及failover的過程,同時比傳統的復制更加安全可靠。由于GTID是連續沒有空洞的,因此主從庫出現數據沖突時,可以通過注入空事物的方式進行跳過。本文主要講述GTID主從架構的錯誤處理方式。

一、GTID的相關特性

配置MySQL GTID 主從復制
基于mysqldump搭建gtid主從

二、GTID如何跳過事務沖突

    很多無法預料的情形導致mysql主從發生事務沖突,主從失敗或停止的情形,即需要修復主從      對于GTID方式的主從架構而言,更多的是處理事務沖突來修復主從      GTID不支持通過傳統設置sql_slave_skip_counter方法來跳過事務      方法:通過注入空事務來填補事務空洞,等同于傳統復制的(set global sql_slave_skip_counter = 1)      步驟:              stop slave;              set gtid_next='xxxxxxx:N'; --指定下一個事務執行的版本,即想要跳過的GTID              begin;              commit;  --注入一個空事物              set gtid_next='AUTOMATIC' --自動的尋找GTID事務。              start slave; --開始同步

三、GTID事務沖突的幾種常見類型

    1、主庫新增記錄,從庫提示主鍵沖突      2、主庫對象可更新,從庫無對應的對象可更新      3、主庫對象可刪除,從庫無對應的對象可刪除      4、通過延遲從修復主庫意外刪除的對象      5、主庫日志被purged的情形

四、示例演示

當前演示的主從架構圖  #?mysqlrplshow?--master=root:pass@192.168.1.233:3306?--discover-slaves-login=root:pass?--verboseWARNING:?Using?a?password?on?the?command?line?interface?can?be?insecure.  #?master?on?192.168.1.233:?...?connected.  #?Finding?slaves?for?master:?192.168.1.233:3306    #?Replication?Topology?Graph  192.168.1.233:3306?(MASTER)???|???+---?192.168.1.245:3306?[IO:?Yes,?SQL:?Yes]?-?(SLAVE)???|???+---?192.168.1.247:3306?[IO:?Yes,?SQL:?Yes]?-?(SLAVE)(root@192.168.1.233)[tempdb]>show?slave?hosts;+-----------+---------------+------+-----------+--------------------------------------+|?Server_id?|?Host??????????|?Port?|?Master_id?|?Slave_UUID???????????????????????????|  +-----------+---------------+------+-----------+--------------------------------------+|???????245?|?192.168.1.245?|?3306?|???????233?|?78336cdc-8cfb-11e6-ba9f-000c29328504?||???????247?|?192.168.1.247?|?3306?|???????233?|?13a26fc1-555a-11e6-b5e0-000c292e1642?|  +-----------+---------------+------+-----------+--------------------------------------+--演示的mysql版本  (root@192.168.1.233)[tempdb]>show?variables?like?'version';+---------------+------------+|?Variable_name?|?Value??????|  +---------------+------------+|?version???????|?5.7.12-log?|  +---------------+------------+--查看gtid是否開啟  (root@192.168.1.233)[tempdb]>show?variables?like?'%gtid_mode%';+---------------+-------+|?Variable_name?|?Value?|  +---------------+-------+|?gtid_mode?????|?ON????|  +---------------+-------+--主庫上面可以看到基于gtid的dump線程,如下  (root@192.168.1.233)[tempdb]>show?processlist;+----+------+-----------------------+--------+------------------+------+|?Id?|?User?|?Host??????????????????|?db?????|?Command??????????|?Time?|  +----+------+-----------------------+--------+------------------+------+|?17?|?repl?|?node245.edq.com:52685?|?NULL???|?Binlog?Dump?GTID?|?2738?|  |?18?|?repl?|?node247.edq.com:33516?|?NULL???|?Binlog?Dump?GTID?|?2690?||?24?|?root?|?localhost?????????????|?tempdb?|?Query????????????|????0?|  +----+------+-----------------------+--------+------------------+------+

1、從庫報主鍵重復(Errno: 1062)

(root@Master)[tempdb]>create?table?t1?(  ????????????->?id?tinyint?not?null?primary?key,ename?varchar(20),blog?varchar(50));    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(1,'leshami','http://blog.csdn.net/leshami');    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');    (root@Master)[tempdb]>set?sql_log_bin=off;    (root@Master)[tempdb]>delete?from?t1?where?ename='robin';    (root@Master)[tempdb]>set?sql_log_bin=on;    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');    --?從庫狀態報錯,提示重復的primary?key  (root@Slave)[tempdb]>show?slave?status?G  ***************************?1.?row?***************************Last_Errno:?1062Last_Error:?Could?not?execute?Write_rows?event?on?table?tempdb.t1;?Duplicate?entry?'2'?for?key?'PRIMARY',?  ????????????????????????Error_code:?1062;?handler?error?HA_ERR_FOUND_DUPP_KEY;?  ????????????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?4426  Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-90  ?Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-89  ?????Auto_Position:?1    --?如下解決方案,可以通過刪除重庫的這條記錄  (root@Slave)[tempdb]>stop?slave;    (root@Slave)[tempdb]>delete?from?t1?where?ename='robin';    (root@Slave)[tempdb]>start?slave;    (root@Slave)[tempdb]>show?slave?status?G  ***************************?1.?row?***************************  ???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-90  ????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-90,  ?78336cdc-8cfb-11e6-ba9f-000c29328504:1??--這里多了一個GTID,注意這個是從庫上執行的,這里的UUID跟IP?245的UUID一致  ????????????????Auto_Position:?1  ?????????Replicate_Rewrite_DB:?  ?????????????????Channel_Name:?  ???????????Master_TLS_Version:?    (root@Slave)[tempdb]>show?variables?like?'%uuid%';  +---------------+--------------------------------------+  |?Variable_name?|?Value????????????????????????????????|  +---------------+--------------------------------------+  |?server_uuid???|?78336cdc-8cfb-11e6-ba9f-000c29328504?|  +---------------+--------------------------------------+

2、從庫報找不到對應的被更新的記錄(Errno: 1032)

--首先在從庫上刪除leshami這條記錄  (root@Slave)[tempdb]>delete?from?t1?where?ename='leshami';    --接下來再主庫嘗試更新leshami這條記錄  (root@Master)[tempdb]>update?t1?set?  ????????????->?blog='http://blog.csdn.net/robinson_0612'?where?ename='leshami';Query?OK,?1?row?affected?(0.02?sec)  Rows?matched:?1??Changed:?1??Warnings:?0    --?查看從庫狀態  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************Last_SQL_Errno:?1032  Last_SQL_Error:?Could?not?execute?Update_rows?event?on?table?tempdb.t1;?Can't?find?record?in?'t1',????????????????????????????????Error_code:?1032;?handler?error?HA_ERR_KEY_NOT_FOUND;????????????????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?4769Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-91  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-90,????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-2--?通過mysqlbinlog在主服務器上尋找報錯的binglog日志文件及位置,找到對應的SQL語句,如下所示  --?update中的where后面的部分為更新前的數據,set部分為更新后的數據,因此可以將更新前的數據插入到從庫#?mysqlbinlog?--no-defaults?-v?-v?--base64-output=DECODE-ROWS?/data/node233-binlog.000004|grep?-A?'10'?4769#161009?13:46:34?server?id?233?end_log_pos?4769?CRC32?0xb60df74e?Update_rows:?table?id?147?flags:?STMT_END_F###?UPDATE?`tempdb`.`t1`###?WHERE###???@1=1?/*?TINYINT?meta=0?nullable=0?is_null=0?*/###???@2='leshami'?/*?VARSTRING(20)?meta=20?nullable=1?is_null=0?*/###???@3='http://blog.csdn.net/leshami'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/###?SET###???@1=1?/*?TINYINT?meta=0?nullable=0?is_null=0?*/###???@2='leshami'?/*?VARSTRING(20)?meta=20?nullable=1?is_null=0?*/###???@3='http://blog.csdn.net/robinson_0612'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/#?at?4769#161009?13:46:34?server?id?233??end_log_pos?4800?CRC32?0xa9669811???????Xid?=?1749COMMIT/*!*/;  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@Slave)[tempdb]>select?*?from?t1;  +----+-------+------------------------------------+  |?id?|?ename?|?blog???????????????????????????????|  +----+-------+------------------------------------+  |??2?|?robin?|?http://www.php.cn/?|  +----+-------+------------------------------------+    (root@Slave)[tempdb]>stop?slave?sql_thread;    (root@Slave)[tempdb]>insert?into?t1?values(1,'leshami','http://blog.csdn.net/leshami');    (root@Slave)[tempdb]>start?slave?sql_thread;    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-91????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-91,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-3????????????????Auto_Position:?1

3、從庫找不到對應的被刪除的記錄(Errno: 1032)

--?如果是在主庫上刪除記錄,而從庫上找不到對應的記錄,則可以直接跳過該事務  --?下面我們首選在從庫上刪除一條記錄  (root@Slave)[tempdb]>delete?from?t1?where?ename='robin';    --?接下來在主庫上刪除該記錄  (root@Master)[tempdb]>delete?from?t1?where?ename='robin';    --?從庫端提示無法找到對應的記錄  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************Last_SQL_Error:?Could?not?execute?Delete_rows?event?on?table?tempdb.t1;?Can't?find?record?in?'t1',????????????????Error_code:?1032;?handler?error?HA_ERR_KEY_NOT_FOUND;?????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?5070Last_SQL_Error_timestamp:?161009?15:08:06????Master_SSL_Crl:?Master_SSL_Crlpath:?  Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-92  ?Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-91,????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4?????Auto_Position:?1??????--?下面通過注入空事務來跳過  (root@Slave)[tempdb]>stop?slave?sql_thread;    (root@Slave)[tempdb]>set?gtid_next='1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:92';    (root@Slave)[tempdb]>begin;commit;    (root@Slave)[tempdb]>set?gtid_next='AUTOMATIC';    (root@Slave)[tempdb]>start?slave?sql_thread;    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-92????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-92,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1?????????Replicate_Rewrite_DB:??????????????????Channel_Name:????????????Master_TLS_Version:

4、延遲從修復主庫意外truncate

--?主庫上面新增表及記錄?????????????  (root@Master)[tempdb]>create?table?t2?(id?tinyint?not?null?primary?key,?  ????????->?ename?varchar(20),blog?varchar(50));(root@Master)[tempdb]>insert?into?t2??  ????????????->?values(1,'leshami','http://blog.csdn.net/leshami');(root@Master)[tempdb]>insert?into?t2??  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');(root@Master)[tempdb]>select?*?from?t2;  +----+---------+------------------------------------+  |?id?|?ename???|?blog???????????????????????????????|  +----+---------+------------------------------------+  |??1?|?leshami?|?http://www.php.cn/???????|  |??2?|?robin???|?http://www.php.cn/?|  +----+---------+------------------------------------+    --先將從庫配置為延遲從  (root@Slave)[tempdb]>stop?slave?sql_thread;  Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>CHANGE?MASTER?TO?MASTER_DELAY?=?300;  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes????????????????????SQL_Delay:?300??root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-99????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-99,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--查看主庫上的binglog?gtid  (root@Master)[tempdb]>show?master?statusG***************************?1.?row?***************************?????????????File:?node233-binlog.000004?????????Position:?6970?????Binlog_Do_DB:?  ?Binlog_Ignore_DB:?  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-99  1?row?in?set?(0.00?sec)    --在主庫上truncate?t2  (root@Master)[tempdb]>truncate?table?t2;  Query?OK,?0?rows?affected?(0.03?sec)    --再次查看主庫上的binglog?gtid,有99變成了100,這個100即是我們需要跳過的ID  (root@Master)[tempdb]>show?master?statusG***************************?1.?row?***************************?????????????File:?node233-binlog.000004?????????Position:?7121?????Binlog_Do_DB:?  ?Binlog_Ignore_DB:?  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100  1?row?in?set?(0.00?sec)    --從庫上跳過被意外truncate的事務  (root@Slave)[tempdb]>stop?slave?sql_thread;  Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>set?gtid_next='1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100';  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>begin;commit;  Query?OK,?0?rows?affected?(0.00?sec)    Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>set?gtid_next='AUTOMATIC';  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000004??????????Read_Master_Log_Pos:?7121???????????????Relay_Log_File:?node245-relay-bin.000003????????????????Relay_Log_Pos:?2982????????Relay_Master_Log_File:?node233-binlog.000004?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes?????????????...........................????????????????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,?????????????????????????????????????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--?很多時候我們并不知道表何時被truncate,因此可以從binlog日志得到其gtid  --?如下所示,可以得到這串?SET?@@SESSION.GTID_NEXT=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100'  --?100即為這個truncate對應的gtid的事務號#?mysqlbinlog?--no-defaults?-v?-v?--base64-output=DECODE-ROWS?/data/node233-binlog.000004|grep?-i?>?"truncate?table?t2"?-A3?-B10??###???@3='http://blog.csdn.net/robinson_0612'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/#?at?6939#161009?18:04:58?server?id?233??end_log_pos?6970?CRC32?0x71c5121c?????Xid?=?1775COMMIT/*!*/;#?at?6970#161009?18:08:42?server?id?233?end_log_pos?7035?CRC32?0x00ba9437?GTID?last_committed=26?sequence_number=27SET?@@SESSION.GTID_NEXT=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100'/*!*/;#?at?7035#161009?18:08:42?server?id?233?end_log_pos?7121?CRC32?0x5a8b9723?Query?thread_id=26?exec_time=0?error_code=0SET?TIMESTAMP=1476007722/*!*/;  truncate?table?t2  /*!*/;  SET?@@SESSION.GTID_NEXT=?'AUTOMATIC'?/*?added?by?mysqlbinlog?*/?/*!*/;  DELIMITER?;

5、主庫binlog被purge的情形(Errno: 1236)

--?首先停止從庫,模擬從庫被意外宕機  (root@Slave)[tempdb]>stop?slave;  Query?OK,?0?rows?affected?(0.08?sec)    --在主庫上進行相應的操作  --此時主庫上的gtid_purged為空  (root@Master)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+-------+  |?Variable_name?|?Value?|  +---------------+-------+  |?gtid_purged???|???????|  +---------------+-------+    --查看主庫binlog  (root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000001?|???1362104?|  |?node233-binlog.000002?|??????1331?|  |?node233-binlog.000003?|???????217?|  |?node233-binlog.000004?|??????7121?|  +-----------------------+-----------+    (root@Master)[tempdb]>select?*?from?t1;  +----+---------+------------------------------------+  |?id?|?ename???|?blog???????????????????????????????|  +----+---------+------------------------------------+  |??1?|?leshami?|?http://www.php.cn/?|  |??2?|?robin???|?http://www.php.cn/???????|  +----+---------+------------------------------------+    --從主庫刪除記錄  (root@Master)[tempdb]>delete?from?t1;    --切換日志  (root@Master)[tempdb]>flush?logs;    --新增記錄  (root@Master)[tempdb]>insert?into?t1?values(1,????->?'xuputi','http://blog.csdn.net/leshami');(root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000001?|???1362104?|  |?node233-binlog.000002?|??????1331?|  |?node233-binlog.000003?|???????217?|  |?node233-binlog.000004?|??????7513?|  |?node233-binlog.000005?|???????490?|  +-----------------------+-----------+    --清理binlog  (root@Master)[tempdb]>purge?binary?logs?to?'node233-binlog.000005';  Query?OK,?0?rows?affected?(0.01?sec)    (root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000005?|???????490?|  +-----------------------+-----------+    --此時可以看到相應的gtid_purged值  (root@Master)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+--------------------------------------------+  |?Variable_name?|?Value??????????????????????????????????????|  +---------------+--------------------------------------------+  |?gtid_purged???|?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101?|  +---------------+--------------------------------------------+    --下面啟動從庫  (root@Slave)[tempdb]>start?slave;  Query?OK,?0?rows?affected?(0.00?sec)    --從庫狀態提示有日志被purged  (root@Slave)[tempdb]>show?slave?statusG***************************?1.?row?***************************???????????????Slave_IO_State:???????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000004??????????Read_Master_Log_Pos:?7121???????????????Relay_Log_File:?node245-relay-bin.000003????????????????Relay_Log_Pos:?3133????????Relay_Master_Log_File:?node233-binlog.000004?????????????Slave_IO_Running:?No????????????Slave_SQL_Running:?Yes????????????????????...............????????????????Last_IO_Errno:?1236????????????????Last_IO_Error:?Got?fatal?error?1236?from?master?when?reading?data?from?binary?log:????????????????'The?slave?is?connecting?using?CHANGE?MASTER?TO?MASTER_AUTO_POSITION?=?1,??????????????????but?the?master?has?purged?binary?logs?containing?GTIDs?that?the?slave?requires.'???????????????????????..................???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--?從庫上gtid_purged參數,此時為75  (root@Slave)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+-------------------------------------------+  |?Variable_name?|?Value?????????????????????????????????????|  +---------------+-------------------------------------------+  |?gtid_purged???|?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-75?|  +---------------+-------------------------------------------+????????????????    --停止從庫  (root@Slave)[tempdb]>stop?slave;  Query?OK,?0?rows?affected?(0.01?sec)    --下面嘗試使用gtid_purged進行跳過事務,,如下,提示僅僅當GLOBAL.GTID_EXECUTED為空才能被設置  (root@Slave)[tempdb]>set?global?gtid_purged?=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101';  ERROR?1840?(HY000):?@@GLOBAL.GTID_PURGED?can?only?be?set?when?@@GLOBAL.GTID_EXECUTED?is?empty.    --如下查看,已經存在被執行的gtid,即gtid_executed肯定是不為空,且這些gtid記錄在從庫的binary?log中  (root@Slave)[tempdb]>show?global?variables?like?'%gtid_executed%'G***************************?1.?row?***************************Variable_name:?gtid_executed????????Value:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,???????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4***************************?2.?row?***************************Variable_name:?gtid_executed_compression_period????????Value:?1000--下面我們在從庫上reset?master,即清空從庫binlog  (root@Slave)[tempdb]>reset?master;  Query?OK,?0?rows?affected?(0.05?sec)    --再次查看gtid_executed已經為空值  (root@Slave)[tempdb]>show?global?variables?like?'%gtid_executed%'G***************************?1.?row?***************************Variable_name:?gtid_executed????????Value:?***************************?2.?row?***************************Variable_name:?gtid_executed_compression_period????????Value:?1000--此時再次設置gtid_purged的值  (root@Slave)[tempdb]>set?global?gtid_purged?=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101';  Query?OK,?0?rows?affected?(0.01?sec)    --啟動從庫  (root@Slave)[tempdb]>start?slave;  Query?OK,?0?rows?affected?(0.03?sec)    --提示有重復記錄,如下所示  --是由于我們在從庫停止期間delete這個事務沒有被從庫的relay?log接受到  --其次主從的binlog又被purged,而且從庫啟動后,執行了gtid_purged,因此主庫上新增的記錄在從庫上提示主鍵重復  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000005??????????Read_Master_Log_Pos:?490???????????????Relay_Log_File:?node245-relay-bin.000004????????????????Relay_Log_Pos:?417????????Relay_Master_Log_File:?node233-binlog.000005?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?No????????????????................???????????????Last_SQL_Error:?Could?not?execute?Write_rows?event?on?table?tempdb.t1;?  ?Duplicate?entry?'1'?for?key?'PRIMARY',?Error_code:?1062;  ?handler?error?HA_ERR_FOUND_DUPP_KEY;?the?event's?master?log?node233-binlog.000005,?end_log_pos?459???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100:102????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101????????????????Auto_Position:?1--在從庫上刪除id為1的記錄  (root@Slave)[tempdb]>delete?from?t1?where?id=1;  Query?OK,?1?row?affected?(0.05?sec)    --啟動從庫的sql_thread線程  (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    --再次查看正常  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000005??????????Read_Master_Log_Pos:?490???????????????Relay_Log_File:?node245-relay-bin.000004????????????????Relay_Log_Pos:?713????????Relay_Master_Log_File:?node233-binlog.000005?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes--上面的這個示例,主要是演示我們使用gtid_purged方式來達到跳過事務的目的  --事實上,主從的數據已經不一致了,應根據實際的需要考慮是否進行相應的修復

五、小結

1、GTID是全局事務ID,簡化了主從架構的部署使得從庫不再需要關心log_file和log_pos
2、由于事務ID的唯一性,使得將其他從庫的GTID應用到其它從庫成為可能,即提供了便利的failover
3、GTID是連續的,非空洞性的,因此,對于沖突的情形,需要注入空的事務來實現
4、可以通過配置延遲從來避免主庫上意外的刪除對象導致的人為錯誤

MySQL GTID是在傳統的mysql主從復制的基礎之上演化而來的產物,即通過UUID加上事務ID的方式來確保每一個事物的唯一性。這樣的操作方式使得我們不再需要關心所謂的log_file和log_Pos,只是簡單的告訴從庫,從哪個服務器上去找主庫就OK了。簡化了主從的搭建以及failover的過程,同時比傳統的復制更加安全可靠。由于GTID是連續沒有空洞的,因此主從庫出現數據沖突時,可以通過注入空事物的方式進行跳過。本文主要講述GTID主從架構的錯誤處理方式。

一、GTID的相關特性

配置MySQL GTID 主從復制
基于mysqldump搭建gtid主從

二、GTID如何跳過事務沖突

    很多無法預料的情形導致mysql主從發生事務沖突,主從失敗或停止的情形,即需要修復主從      對于GTID方式的主從架構而言,更多的是處理事務沖突來修復主從      GTID不支持通過傳統設置sql_slave_skip_counter方法來跳過事務      方法:通過注入空事務來填補事務空洞,等同于傳統復制的(set global sql_slave_skip_counter = 1)      步驟:              stop slave;              set gtid_next='xxxxxxx:N'; --指定下一個事務執行的版本,即想要跳過的GTID              begin;              commit;  --注入一個空事物              set gtid_next='AUTOMATIC' --自動的尋找GTID事務。              start slave; --開始同步

三、GTID事務沖突的幾種常見類型

    1、主庫新增記錄,從庫提示主鍵沖突      2、主庫對象可更新,從庫無對應的對象可更新      3、主庫對象可刪除,從庫無對應的對象可刪除      4、通過延遲從修復主庫意外刪除的對象      5、主庫日志被purged的情形

四、示例演示

當前演示的主從架構圖  #?mysqlrplshow?--master=root:pass@192.168.1.233:3306?--discover-slaves-login=root:pass?--verboseWARNING:?Using?a?password?on?the?command?line?interface?can?be?insecure.  #?master?on?192.168.1.233:?...?connected.  #?Finding?slaves?for?master:?192.168.1.233:3306    #?Replication?Topology?Graph  192.168.1.233:3306?(MASTER)???|???+---?192.168.1.245:3306?[IO:?Yes,?SQL:?Yes]?-?(SLAVE)???|???+---?192.168.1.247:3306?[IO:?Yes,?SQL:?Yes]?-?(SLAVE)(root@192.168.1.233)[tempdb]>show?slave?hosts;+-----------+---------------+------+-----------+--------------------------------------+|?Server_id?|?Host??????????|?Port?|?Master_id?|?Slave_UUID???????????????????????????|  +-----------+---------------+------+-----------+--------------------------------------+|???????245?|?192.168.1.245?|?3306?|???????233?|?78336cdc-8cfb-11e6-ba9f-000c29328504?||???????247?|?192.168.1.247?|?3306?|???????233?|?13a26fc1-555a-11e6-b5e0-000c292e1642?|  +-----------+---------------+------+-----------+--------------------------------------+--演示的mysql版本  (root@192.168.1.233)[tempdb]>show?variables?like?'version';+---------------+------------+|?Variable_name?|?Value??????|  +---------------+------------+|?version???????|?5.7.12-log?|  +---------------+------------+--查看gtid是否開啟  (root@192.168.1.233)[tempdb]>show?variables?like?'%gtid_mode%';+---------------+-------+|?Variable_name?|?Value?|  +---------------+-------+|?gtid_mode?????|?ON????|  +---------------+-------+--主庫上面可以看到基于gtid的dump線程,如下  (root@192.168.1.233)[tempdb]>show?processlist;+----+------+-----------------------+--------+------------------+------+|?Id?|?User?|?Host??????????????????|?db?????|?Command??????????|?Time?|  +----+------+-----------------------+--------+------------------+------+|?17?|?repl?|?node245.edq.com:52685?|?NULL???|?Binlog?Dump?GTID?|?2738?|  |?18?|?repl?|?node247.edq.com:33516?|?NULL???|?Binlog?Dump?GTID?|?2690?||?24?|?root?|?localhost?????????????|?tempdb?|?Query????????????|????0?|  +----+------+-----------------------+--------+------------------+------+

1、從庫報主鍵重復(Errno: 1062)

(root@Master)[tempdb]>create?table?t1?(  ????????????->?id?tinyint?not?null?primary?key,ename?varchar(20),blog?varchar(50));    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(1,'leshami','http://blog.csdn.net/leshami');    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');    (root@Master)[tempdb]>set?sql_log_bin=off;    (root@Master)[tempdb]>delete?from?t1?where?ename='robin';    (root@Master)[tempdb]>set?sql_log_bin=on;    (root@Master)[tempdb]>insert?into?t1?  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');    --?從庫狀態報錯,提示重復的primary?key  (root@Slave)[tempdb]>show?slave?status?G  ***************************?1.?row?***************************Last_Errno:?1062Last_Error:?Could?not?execute?Write_rows?event?on?table?tempdb.t1;?Duplicate?entry?'2'?for?key?'PRIMARY',?  ????????????????????????Error_code:?1062;?handler?error?HA_ERR_FOUND_DUPP_KEY;?  ????????????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?4426  Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-90  ?Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-89  ?????Auto_Position:?1    --?如下解決方案,可以通過刪除重庫的這條記錄  (root@Slave)[tempdb]>stop?slave;    (root@Slave)[tempdb]>delete?from?t1?where?ename='robin';    (root@Slave)[tempdb]>start?slave;    (root@Slave)[tempdb]>show?slave?status?G  ***************************?1.?row?***************************  ???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-90  ????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-90,  ?78336cdc-8cfb-11e6-ba9f-000c29328504:1??--這里多了一個GTID,注意這個是從庫上執行的,這里的UUID跟IP?245的UUID一致  ????????????????Auto_Position:?1  ?????????Replicate_Rewrite_DB:?  ?????????????????Channel_Name:?  ???????????Master_TLS_Version:?    (root@Slave)[tempdb]>show?variables?like?'%uuid%';  +---------------+--------------------------------------+  |?Variable_name?|?Value????????????????????????????????|  +---------------+--------------------------------------+  |?server_uuid???|?78336cdc-8cfb-11e6-ba9f-000c29328504?|  +---------------+--------------------------------------+

2、從庫報找不到對應的被更新的記錄(Errno: 1032)

--首先在從庫上刪除leshami這條記錄  (root@Slave)[tempdb]>delete?from?t1?where?ename='leshami';    --接下來再主庫嘗試更新leshami這條記錄  (root@Master)[tempdb]>update?t1?set?  ????????????->?blog='http://blog.csdn.net/robinson_0612'?where?ename='leshami';Query?OK,?1?row?affected?(0.02?sec)  Rows?matched:?1??Changed:?1??Warnings:?0    --?查看從庫狀態  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************Last_SQL_Errno:?1032  Last_SQL_Error:?Could?not?execute?Update_rows?event?on?table?tempdb.t1;?Can't?find?record?in?'t1',????????????????????????????????Error_code:?1032;?handler?error?HA_ERR_KEY_NOT_FOUND;????????????????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?4769Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-91  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-90,????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-2--?通過mysqlbinlog在主服務器上尋找報錯的binglog日志文件及位置,找到對應的SQL語句,如下所示  --?update中的where后面的部分為更新前的數據,set部分為更新后的數據,因此可以將更新前的數據插入到從庫#?mysqlbinlog?--no-defaults?-v?-v?--base64-output=DECODE-ROWS?/data/node233-binlog.000004|grep?-A?'10'?4769#161009?13:46:34?server?id?233?end_log_pos?4769?CRC32?0xb60df74e?Update_rows:?table?id?147?flags:?STMT_END_F###?UPDATE?`tempdb`.`t1`###?WHERE###???@1=1?/*?TINYINT?meta=0?nullable=0?is_null=0?*/###???@2='leshami'?/*?VARSTRING(20)?meta=20?nullable=1?is_null=0?*/###???@3='http://blog.csdn.net/leshami'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/###?SET###???@1=1?/*?TINYINT?meta=0?nullable=0?is_null=0?*/###???@2='leshami'?/*?VARSTRING(20)?meta=20?nullable=1?is_null=0?*/###???@3='http://blog.csdn.net/robinson_0612'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/#?at?4769#161009?13:46:34?server?id?233??end_log_pos?4800?CRC32?0xa9669811???????Xid?=?1749COMMIT/*!*/;  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@Slave)[tempdb]>select?*?from?t1;  +----+-------+------------------------------------+  |?id?|?ename?|?blog???????????????????????????????|  +----+-------+------------------------------------+  |??2?|?robin?|?http://www.php.cn/?|  +----+-------+------------------------------------+    (root@Slave)[tempdb]>stop?slave?sql_thread;    (root@Slave)[tempdb]>insert?into?t1?values(1,'leshami','http://blog.csdn.net/leshami');    (root@Slave)[tempdb]>start?slave?sql_thread;    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-91????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-91,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-3????????????????Auto_Position:?1

3、從庫找不到對應的被刪除的記錄(Errno: 1032)

--?如果是在主庫上刪除記錄,而從庫上找不到對應的記錄,則可以直接跳過該事務  --?下面我們首選在從庫上刪除一條記錄  (root@Slave)[tempdb]>delete?from?t1?where?ename='robin';    --?接下來在主庫上刪除該記錄  (root@Master)[tempdb]>delete?from?t1?where?ename='robin';    --?從庫端提示無法找到對應的記錄  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************Last_SQL_Error:?Could?not?execute?Delete_rows?event?on?table?tempdb.t1;?Can't?find?record?in?'t1',????????????????Error_code:?1032;?handler?error?HA_ERR_KEY_NOT_FOUND;?????????????????the?event's?master?log?node233-binlog.000004,?end_log_pos?5070Last_SQL_Error_Timestamp:?161009?15:08:06????Master_SSL_Crl:?Master_SSL_Crlpath:?  Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-92  ?Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-91,????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4?????Auto_Position:?1??????--?下面通過注入空事務來跳過  (root@Slave)[tempdb]>stop?slave?sql_thread;    (root@Slave)[tempdb]>set?gtid_next='1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:92';    (root@Slave)[tempdb]>begin;commit;    (root@Slave)[tempdb]>set?gtid_next='AUTOMATIC';    (root@Slave)[tempdb]>start?slave?sql_thread;    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-92????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-92,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1?????????Replicate_Rewrite_DB:??????????????????Channel_Name:????????????Master_TLS_Version:

4、延遲從修復主庫意外truncate

--?主庫上面新增表及記錄?????????????  (root@Master)[tempdb]>create?table?t2?(id?tinyint?not?null?primary?key,?  ????????->?ename?varchar(20),blog?varchar(50));(root@Master)[tempdb]>insert?into?t2??  ????????????->?values(1,'leshami','http://blog.csdn.net/leshami');(root@Master)[tempdb]>insert?into?t2??  ????????????->?values(2,'robin','http://blog.csdn.net/robinson_0612');(root@Master)[tempdb]>select?*?from?t2;  +----+---------+------------------------------------+  |?id?|?ename???|?blog???????????????????????????????|  +----+---------+------------------------------------+  |??1?|?leshami?|?http://www.php.cn/???????|  |??2?|?robin???|?http://www.php.cn/?|  +----+---------+------------------------------------+    --先將從庫配置為延遲從  (root@Slave)[tempdb]>stop?slave?sql_thread;  Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>CHANGE?MASTER?TO?MASTER_DELAY?=?300;  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes????????????????????SQL_Delay:?300??root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-99????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-99,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--查看主庫上的binglog?gtid  (root@Master)[tempdb]>show?master?statusG***************************?1.?row?***************************?????????????File:?node233-binlog.000004?????????Position:?6970?????Binlog_Do_DB:?  ?Binlog_Ignore_DB:?  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-99  1?row?in?set?(0.00?sec)    --在主庫上truncate?t2  (root@Master)[tempdb]>truncate?table?t2;  Query?OK,?0?rows?affected?(0.03?sec)    --再次查看主庫上的binglog?gtid,有99變成了100,這個100即是我們需要跳過的ID  (root@Master)[tempdb]>show?master?statusG***************************?1.?row?***************************?????????????File:?node233-binlog.000004?????????Position:?7121?????Binlog_Do_DB:?  ?Binlog_Ignore_DB:?  Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100  1?row?in?set?(0.00?sec)    --從庫上跳過被意外truncate的事務  (root@Slave)[tempdb]>stop?slave?sql_thread;  Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>set?gtid_next='1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100';  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>begin;commit;  Query?OK,?0?rows?affected?(0.00?sec)    Query?OK,?0?rows?affected?(0.01?sec)    (root@Slave)[tempdb]>set?gtid_next='AUTOMATIC';  Query?OK,?0?rows?affected?(0.00?sec)    (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000004??????????Read_Master_Log_Pos:?7121???????????????Relay_Log_File:?node245-relay-bin.000003????????????????Relay_Log_Pos:?2982????????Relay_Master_Log_File:?node233-binlog.000004?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes?????????????...........................????????????????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,?????????????????????????????????????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--?很多時候我們并不知道表何時被truncate,因此可以從binlog日志得到其gtid  --?如下所示,可以得到這串?SET?@@SESSION.GTID_NEXT=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100'  --?100即為這個truncate對應的gtid的事務號#?mysqlbinlog?--no-defaults?-v?-v?--base64-output=DECODE-ROWS?/data/node233-binlog.000004|grep?-i?>?"truncate?table?t2"?-A3?-B10??###???@3='http://blog.csdn.net/robinson_0612'?/*?VARSTRING(50)?meta=50?nullable=1?is_null=0?*/#?at?6939#161009?18:04:58?server?id?233??end_log_pos?6970?CRC32?0x71c5121c?????Xid?=?1775COMMIT/*!*/;#?at?6970#161009?18:08:42?server?id?233?end_log_pos?7035?CRC32?0x00ba9437?GTID?last_committed=26?sequence_number=27SET?@@SESSION.GTID_NEXT=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:100'/*!*/;#?at?7035#161009?18:08:42?server?id?233?end_log_pos?7121?CRC32?0x5a8b9723?Query?thread_id=26?exec_time=0?error_code=0SET?TIMESTAMP=1476007722/*!*/;  truncate?table?t2  /*!*/;  SET?@@SESSION.GTID_NEXT=?'AUTOMATIC'?/*?added?by?mysqlbinlog?*/?/*!*/;  DELIMITER?;

5、主庫binlog被purge的情形(Errno: 1236)

--?首先停止從庫,模擬從庫被意外宕機  (root@Slave)[tempdb]>stop?slave;  Query?OK,?0?rows?affected?(0.08?sec)    --在主庫上進行相應的操作  --此時主庫上的gtid_purged為空  (root@Master)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+-------+  |?Variable_name?|?Value?|  +---------------+-------+  |?gtid_purged???|???????|  +---------------+-------+    --查看主庫binlog  (root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000001?|???1362104?|  |?node233-binlog.000002?|??????1331?|  |?node233-binlog.000003?|???????217?|  |?node233-binlog.000004?|??????7121?|  +-----------------------+-----------+    (root@Master)[tempdb]>select?*?from?t1;  +----+---------+------------------------------------+  |?id?|?ename???|?blog???????????????????????????????|  +----+---------+------------------------------------+  |??1?|?leshami?|?http://www.php.cn/?|  |??2?|?robin???|?http://www.php.cn/???????|  +----+---------+------------------------------------+    --從主庫刪除記錄  (root@Master)[tempdb]>delete?from?t1;    --切換日志  (root@Master)[tempdb]>flush?logs;    --新增記錄  (root@Master)[tempdb]>insert?into?t1?values(1,????->?'xuputi','http://blog.csdn.net/leshami');(root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000001?|???1362104?|  |?node233-binlog.000002?|??????1331?|  |?node233-binlog.000003?|???????217?|  |?node233-binlog.000004?|??????7513?|  |?node233-binlog.000005?|???????490?|  +-----------------------+-----------+    --清理binlog  (root@Master)[tempdb]>purge?binary?logs?to?'node233-binlog.000005';  Query?OK,?0?rows?affected?(0.01?sec)    (root@Master)[tempdb]>show?binary?logs;  +-----------------------+-----------+  |?Log_name??????????????|?File_size?|  +-----------------------+-----------+  |?node233-binlog.000005?|???????490?|  +-----------------------+-----------+    --此時可以看到相應的gtid_purged值  (root@Master)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+--------------------------------------------+  |?Variable_name?|?Value??????????????????????????????????????|  +---------------+--------------------------------------------+  |?gtid_purged???|?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101?|  +---------------+--------------------------------------------+    --下面啟動從庫  (root@Slave)[tempdb]>start?slave;  Query?OK,?0?rows?affected?(0.00?sec)    --從庫狀態提示有日志被purged  (root@Slave)[tempdb]>show?slave?statusG***************************?1.?row?***************************???????????????Slave_IO_State:???????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000004??????????Read_Master_Log_Pos:?7121???????????????Relay_Log_File:?node245-relay-bin.000003????????????????Relay_Log_Pos:?3133????????Relay_Master_Log_File:?node233-binlog.000004?????????????Slave_IO_Running:?No????????????Slave_SQL_Running:?Yes????????????????????...............????????????????Last_IO_Errno:?1236????????????????Last_IO_Error:?Got?fatal?error?1236?from?master?when?reading?data?from?binary?log:????????????????'The?slave?is?connecting?using?CHANGE?MASTER?TO?MASTER_AUTO_POSITION?=?1,??????????????????but?the?master?has?purged?binary?logs?containing?GTIDs?that?the?slave?requires.'???????????????????????..................???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,???????????????????????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4????????????????Auto_Position:?1--?從庫上gtid_purged參數,此時為75  (root@Slave)[tempdb]>show?variables?like?'%gtid_purged%';  +---------------+-------------------------------------------+  |?Variable_name?|?Value?????????????????????????????????????|  +---------------+-------------------------------------------+  |?gtid_purged???|?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-75?|  +---------------+-------------------------------------------+????????????????    --停止從庫  (root@Slave)[tempdb]>stop?slave;  Query?OK,?0?rows?affected?(0.01?sec)    --下面嘗試使用gtid_purged進行跳過事務,,如下,提示僅僅當GLOBAL.GTID_EXECUTED為空才能被設置  (root@Slave)[tempdb]>set?global?gtid_purged?=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101';  ERROR?1840?(HY000):?@@GLOBAL.GTID_PURGED?can?only?be?set?when?@@GLOBAL.GTID_EXECUTED?is?empty.    --如下查看,已經存在被執行的gtid,即gtid_executed肯定是不為空,且這些gtid記錄在從庫的binary?log中  (root@Slave)[tempdb]>show?global?variables?like?'%gtid_executed%'G***************************?1.?row?***************************Variable_name:?gtid_executed????????Value:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-100,???????????????78336cdc-8cfb-11e6-ba9f-000c29328504:1-4***************************?2.?row?***************************Variable_name:?gtid_executed_compression_period????????Value:?1000--下面我們在從庫上reset?master,即清空從庫binlog  (root@Slave)[tempdb]>reset?master;  Query?OK,?0?rows?affected?(0.05?sec)    --再次查看gtid_executed已經為空值  (root@Slave)[tempdb]>show?global?variables?like?'%gtid_executed%'G***************************?1.?row?***************************Variable_name:?gtid_executed????????Value:?***************************?2.?row?***************************Variable_name:?gtid_executed_compression_period????????Value:?1000--此時再次設置gtid_purged的值  (root@Slave)[tempdb]>set?global?gtid_purged?=?'1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101';  Query?OK,?0?rows?affected?(0.01?sec)    --啟動從庫  (root@Slave)[tempdb]>start?slave;  Query?OK,?0?rows?affected?(0.03?sec)    --提示有重復記錄,如下所示  --是由于我們在從庫停止期間delete這個事務沒有被從庫的relay?log接受到  --其次主從的binlog又被purged,而且從庫啟動后,執行了gtid_purged,因此主庫上新增的記錄在從庫上提示主鍵重復  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000005??????????Read_Master_Log_Pos:?490???????????????Relay_Log_File:?node245-relay-bin.000004????????????????Relay_Log_Pos:?417????????Relay_Master_Log_File:?node233-binlog.000005?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?No????????????????................???????????????Last_SQL_Error:?Could?not?execute?Write_rows?event?on?table?tempdb.t1;?  ?Duplicate?entry?'1'?for?key?'PRIMARY',?Error_code:?1062;  ?handler?error?HA_ERR_FOUND_DUPP_KEY;?the?event's?master?log?node233-binlog.000005,?end_log_pos?459???????????Retrieved_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:76-100:102????????????Executed_Gtid_Set:?1b64c25d-8d2b-11e6-9ac0-000c29b82d0d:1-101????????????????Auto_Position:?1--在從庫上刪除id為1的記錄  (root@Slave)[tempdb]>delete?from?t1?where?id=1;  Query?OK,?1?row?affected?(0.05?sec)    --啟動從庫的sql_thread線程  (root@Slave)[tempdb]>start?slave?sql_thread;  Query?OK,?0?rows?affected?(0.02?sec)    --再次查看正常  (root@Slave)[tempdb]>show?slave?status?G***************************?1.?row?***************************???????????????Slave_IO_State:?Waiting?for?master?to?send?event??????????????????Master_Host:?Master??????????????????Master_User:?repl??????????????????Master_Port:?3306????????????????Connect_Retry:?60??????????????Master_Log_File:?node233-binlog.000005??????????Read_Master_Log_Pos:?490???????????????Relay_Log_File:?node245-relay-bin.000004????????????????Relay_Log_Pos:?713????????Relay_Master_Log_File:?node233-binlog.000005?????????????Slave_IO_Running:?Yes????????????Slave_SQL_Running:?Yes--上面的這個示例,主要是演示我們使用gtid_purged方式來達到跳過事務的目的  --事實上,主從的數據已經不一致了,應根據實際的需要考慮是否進行相應的修復

五、小結

1、GTID是全局事務ID,簡化了主從架構的部署使得從庫不再需要關心log_file和log_pos
2、由于事務ID的唯一性,使得將其他從庫的GTID應用到其它從庫成為可能,即提供了便利的failover
3、GTID是連續的,非空洞性的,因此,對于沖突的情形,需要注入空的事務來實現
4、可以通過配置延遲從來避免主庫上意外的刪除對象導致的人為錯誤

以上就是的內容,更多相關內容請關注PHP中文網(www.php.cn)!

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享