常見GTID主從複製報錯及處理思路

測試環境(已經事先搭建好GTID主從環境)
MySQL5.7.16--01 3307 主  
MySQL5.7.16--02 3308 從


準備:
在主庫建表,插入測試數據
CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
insert into t(name) values('小米'),('小郭'),('小華'),('小歐');


root@localhost:mysql3307.sock [test]>select * from t;
+----+--------+
| id | name   |
+----+--------+
|  1 | 小米   |
|  2 | 小郭   |
|  3 | 小華   |
|  4 | 小歐   |
+----+--------+
4 rows in set (0.00 sec)


1、從庫複製報錯1050
執行show slave status\G查看錯誤信息
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Errno: 1050
Last_Error: Error 'Table 't' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
sql線程中斷,報錯信息顯示t表在從庫上已經存在,IO線程將relay-log解析回放的過程中該事務無法執行
通過查看Executed_Gtid_Set參數
主庫:
root@localhost:mysql3307.sock [test]>show master status;
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                   |
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+
| mysql-bin.000007 |     1143 |              |                  | ac06a58c-cd84-11e6-bdf1-525400a9938f:1-37,
c8e2d47f-cd6e-11e6-905c-525400a9938f:1-8 |
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
從庫:
Executed_Gtid_Set: ac06a58c-cd84-11e6-bdf1-525400a9938f:1-35,


從庫在35(包含35)之前的事務都已經正常執行完成,而主庫已經執行到事務37,說明事務36在從庫上沒有正常執行,事務36就是報錯的DML
語句。
所以思路很簡單直接刪除從庫的t表,讓事務36得到正常執行就能解決問題。
從庫:
drop table t;
start slave;
show slave status\G 查看SQL和IO線程都爲yes,確認修復




2、1062主鍵衝突(適合解決少數量主鍵衝突)
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table test.t; Duplicate entry '4' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; 
the event's master log mysql-bin.000007, end_log_pos 1375
接下來我們可以在主庫上看下binlog執行了什麼語句導致的
mysqlbinlog --base64-output=decode-row -v -v mysql-bin.000007 >07.sql
#161229 17:56:35 server id 1003307  end_log_pos 1375 CRC32 0xdea6ed27   Write_rows: table id 122 flags: STMT_END_F
### INSERT INTO `test`.`t`
### SET
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2='大神v' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
# at 1375
#161229 17:56:35 server id 1003307  end_log_pos 1406 CRC32 0x12dcd47c   Xid = 144
COMMIT/*!*/;
主庫:
root@localhost:mysql3307.sock [test]>select * from t where id=4;
+----+---------+
| id | name    |
+----+---------+
|  4 | 大神v   |
+----+---------+
1 row in set (0.00 sec)
從庫:
root@localhost:mysql3308.sock [test]>select * from t where id=4;
+----+--------+
| id | name   |
+----+--------+
|  4 | 小歐   |
+----+--------+
1 row in set (0.00 sec)


從庫主鍵4已經存在
修復:
delete from t where id=4;
start slave;




3、更新找不到記錄 1032報錯
故意將主從數據不一致
root@localhost:mysql3307.sock [test]>select * from t;
+----+---------+
| id | name    |
+----+---------+
|  1 | 小米    |
|  2 | 小郭    |
|  3 | 小華    |
|  4 | 大神v   |
|  5 | 戴斯    |
+----+---------+
5 rows in set (0.00 sec)
root@localhost:mysql3308.sock [test]>select * from t;
+----+---------+
| id | name    |
+----+---------+
|  1 | 小米    |
|  2 | 小郭    |
|  3 | 小華    |
|  4 | 大神v   |
+----+---------+
4 rows in set (0.00 sec)


update t set name='小雞' where id=5;


報錯信息:
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Update_rows event on table test.t; Can't find record in 't', 
Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000007, end_log_pos 1650
思路和之前一樣,查看binlog鎖定主庫執行的sql
mysqlbinlog --base64-output=decode-row -v -v mysql-bin.000007 >07.sql
#161229 18:19:15 server id 1003307  end_log_pos 1650 CRC32 0x0b598bd9   Update_rows: table id 122 flags: STMT_END_F
### UPDATE `test`.`t`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2='戴斯' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2='小雞' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
# at 1650
#161229 18:19:15 server id 1003307  end_log_pos 1681 CRC32 0x781b6ae1   Xid = 153
COMMIT/*!*/;
知道是在主庫執行了對id=5的行update導致,查看下從庫沒有id=5的主鍵,這個時候我們自己手動加一條上去
修復:
insert into t(id,name) values(5,'睡覺睡覺');
start slave;


4. delete 找不到記錄 1032報錯
delete from t where id=5;
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table test.t; Can't find record in 't', 
Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000007, end_log_pos 1912
這個錯誤有2種解決方式:
方法一、還是前面的思路,在binlog中根據log_pos找到delete語句
#161229 18:29:35 server id 1003307  end_log_pos 1912 CRC32 0x8166304d   Delete_rows: table id 122 flags: STMT_END_F
### DELETE FROM `test`.`t`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2='小雞' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
# at 1912
#161229 18:29:35 server id 1003307  end_log_pos 1943 CRC32 0xa1a89910   Xid = 155
COMMIT/*!*/;
是刪除主鍵id=5的行導致的報錯,思路就是在從庫插入一條id=5的行,讓事務能夠順利執行下去,就能解決報錯
修復:
insert into t(id,name) values(5,'小感動');
start slave;


方法二:執行跳過這個事務,因爲是delete操作,跳過不會影響主從數據一致性
show slave status\G
查看參數:Retrieved_Gtid_Set   Executed_Gtid_Set
Retrieved_Gtid_Set: ac06a58c-cd84-11e6-bdf1-525400a9938f:1-77,
Executed_Gtid_Set: ac06a58c-cd84-11e6-bdf1-525400a9938f:1-61,
我們看到從庫已經將事務61(包含61)之前的事務全部完成,主庫的source_id:ac06a58c-cd84-11e6-bdf1-525400a9938f 1-77是主庫執行到的事務ID
說明從庫在執行事務ID62的時候無法執行,造成主從不同步,所以直接跳過事務ID 62
步驟:
stop slave;
set gtid_next='ac06a58c-cd84-11e6-bdf1-525400a9938f:62';
begin;commit;
set gtid_next='automatic';
start slave;


結語:這是幾種常見的小故障,主要是一個處理的思路,一切還是以生存環境爲準,多看,多想,最重要的還是多操作。



































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章