MySQL GTID複製錯誤修復演示

abstractcyj發表於2021-11-23

GTID 組成

GTID 實際上就是全域性事務ID 的意思

GTID 可以理解成資料庫服務的UUID 加上一個或者一段區間內的事務id 組成

如:
2310c727-4b3a-11ec-a3fe-000c2963ed70:1-5

 

2310c727-4b3a-11ec-a3fe-000c2963ed70 即為源端(MySQL 8 稱為源端,MySQL 5.7 稱為Master) UUID
如下:
mysql> show variables like '%uuid%';

+---------------+--------------------------------------+

| Variable_name | Value                                |

+---------------+--------------------------------------+

| server_uuid   | 2310c727-4b3a-11ec-a3fe-000c2963ed70 |

+---------------+--------------------------------------+

 

1-5 表示1 號到5 號事務

 

 

需要注意的是,並不是每個事務都會產生GTID 。我們可以採用”SET @@SESSION.sql_log_bin = 0“ 的方式,將事務不去寫入binlog, 這樣這個事務也不會被授予GTID .

 

 

GTID 相關係統引數

比較重要的引數如下:

 

GTID_NEXT :這個引數作用域是session 用於指示目標端下個需要執行的事務

GTID_EXECUTED: 資料庫已經執行的事務。注意,如果是雙主複製,這裡會存在多個服務端的UUID 資訊

 

模擬錯誤

雙主GTID 複製搭建的過程在這裡跳過。網路上有很多這樣的文件。

我們需要使用引數:

SET @@SESSION.sql_log_bin = 0

 

以下我們以server1 代表主節點,server2 代表從節點, 因為我們是雙主複製,嚴格來說並沒有主從之分。

 

首先在server1 建立表,並插入資料:

指令碼如下:
create table t1(

  id bigint,

  name varchar(100)

) engine innodb;

 

insert into t1(id , name) values(1, 'AA'),(2, 'AB'),(3, 'BB')

 

 

可以看到操作很快就在server2 上被應用。

 

緊接著在server2 上操作,為表t1 建立主鍵:
SET @@SESSION.sql_log_bin = 0

alter table t1 add primary key pk_t1(id);

 

請記住,這個操作並不會被複制到server1, 因為它根本沒有寫入到binlog

 

緊接著在server1 執行

alter table t1 add primary key pk_t1(id);

 

我們很快就看到server2 SQL 執行緒出錯

2021-11-23T06:15:02.442351Z 12 [System] [MY-010597] [Repl] 'CHANGE MASTER TO FOR CHANNEL '' executed'. Previous state master_host='192.168.177.128', master_port= 3306, master_log_file='mysql-bin.000001', master_log_pos= 6248, master_bind=''. New state master_host='192.168.177.128', master_port= 3306, master_log_file='', master_log_pos= 4, master_bind=''.

2021-11-23T06:15:20.384619Z 21 [Warning] [MY-010897] [Repl] Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommen2021-11-23T06:17:52.273249Z 23 [ERROR] [MY-010584] [Repl] Slave SQL for channel '': Worker 1 failed executing transaction '2310c727-4b3a-11ec-a3fe-000c2963ed70:5' at master log mysql-bin.000004, end_log_pos 1795; Error 'Multiple primary key defined' on query. Default database: 'testdb'. Query: 'alter table t1 add primary key pk_t1(id)', Error_code: MY-001068

2021-11-23T06:17:52.273559Z 22 [Warning] [MY-010584] [Repl] Slave SQL for channel '': ... The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details). Error_code: MY-001756

ded. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.

2021-11-23T06:15:20.482973Z 21 [System] [MY-010562] [Repl] Slave I/O thread for channel '': connected to master 'repl128@192.168.177.128:3306',replication started in log 'FIRST' at position 4

 

修復錯誤

首先在檢視server2 相關gtid 引數:
mysql> show variables like '%gtid%';

+----------------------------------+-------------------------------------------------------------------------------------+

| Variable_name                    | Value                                                                               |

+----------------------------------+-------------------------------------------------------------------------------------+

| binlog_gtid_simple_recovery      | ON                                                                                  |

| enforce_gtid_consistency         | ON                                                                                  |

| gtid_executed                    | 2310c727-4b3a-11ec-a3fe-000c2963ed70:1-4,

f5cbfe67-4b33-11ec-89ec-000c29f1372b:1-19 |

| gtid_executed_compression_period | 0                                                                                   |

| gtid_mode                        | ON                                                                                  |

| gtid_next                        | AUTOMATIC                                                                           |

| gtid_owned                       |                                                                                     |

| gtid_purged                      |                                                                                     |

| session_track_gtids              | OFF                                                                                 |

+----------------------------------+-------------------

server1 相關引數

mysql> show variables like '%gtid%';

+----------------------------------+-------------------------------------------------------------------------------------+

| Variable_name                    | Value                                                                               |

+----------------------------------+-------------------------------------------------------------------------------------+

| binlog_gtid_simple_recovery      | ON                                                                                  |

| enforce_gtid_consistency         | ON                                                                                  |

| gtid_executed                    | 2310c727-4b3a-11ec-a3fe-000c2963ed70:1-5,

f5cbfe67-4b33-11ec-89ec-000c29f1372b:1-19 |

| gtid_executed_compression_period | 0                                                                                   |

| gtid_mode                        | ON                                                                                  |

| gtid_next                        | AUTOMATIC                                                                           |

| gtid_owned                       |                                                                                     |

| gtid_purged                      |                                                                                     |

| session_track_gtids              | OFF                                                                                 |

+----------------------------------+-------------------------------------------------------------------------------------+

 

可以看到server1 多了一個事務: 2310c727-4b3a-11ec-a3fe-000c2963ed70:5

 

我們需要在出錯的server1 上跳過這個事務

執行以下操作即可:
stop replica

 SET GTID_NEXT= '2310c727-4b3a-11ec-a3fe-000c2963ed70:5';

 BEGIN; COMMIT;

SET SESSION GTID_NEXT = AUTOMATIC;

start replica

總結

對於這個case, 若是實際生產環境中,因為誤操作導致表t1 主鍵在server1, server2 上不一致,本身複製已經出現了問題,我們需要在給缺失主鍵的節點上增加主鍵時,不要把增加主鍵的這個事務寫入到binlog 。需要的操作其實是:
SET @@SESSION.sql_log_bin = 0

alter table t1 add primary key pk_t1(id);

 

如果我們已經把這個操作錯誤的寫入了binlog, 那麼我們需要做的是如何定位去定位這個需要跳過的GTID 。理解了gtid_executed gtid_next 這兩個引數,其實類似錯誤處理起來也比較容易了


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8520577/viewspace-2843661/,如需轉載,請註明出處,否則將追究法律責任。

相關文章