如果複製因複製交易中的事件問題而停止,您可以透過跳過副本上失敗的交易來繼續複製。在跳過交易之前,請確保複製 I/O (接收器) 執行緒以及 SQL (套用程式) 執行緒都已停止。
首先,您需要識別導致錯誤的複製事件。錯誤的詳細資訊以及最後成功套用的交易會記錄在效能架構(Performance Schema)的 replication_applier_status_by_worker
表格中。您可以使用 mysqlbinlog 來檢索和顯示錯誤發生前後記錄的事件。關於如何執行此操作的說明,請參閱第 9.5 節,「時間點(增量)復原」。或者,您可以在副本上執行 SHOW RELAYLOG EVENTS
,或在來源上執行 SHOW BINLOG EVENTS
。
在跳過交易並重新啟動副本之前,請檢查以下幾點:
停止複製的交易是否來自不明或不信任的來源?如果是,請調查原因,以防有任何安全考量表明不應重新啟動副本。
停止複製的交易是否需要在副本上套用?如果是,請進行適當的更正並重新套用交易,或手動在副本上協調資料。
停止複製的交易是否需要在來源上套用?如果不是,請在最初發生交易的伺服器上手動撤銷該交易。
若要跳過交易,請選擇下列其中一種適當的方法:
當使用 GTID 時(
gtid_mode
為ON
),請參閱第 19.1.7.3.1 節,「使用 GTID 跳過交易」。當未使用 GTID 或正在逐步導入 GTID 時(
gtid_mode
為OFF
、OFF_PERMISSIVE
或ON_PERMISSIVE
),請參閱第 19.1.7.3.2 節,「不使用 GTID 跳過交易」。如果您使用
CHANGE REPLICATION SOURCE TO
陳述式的ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
選項,在複製通道上啟用了 GTID 指派,請參閱第 19.1.7.3.2 節,「不使用 GTID 跳過交易」。在複製通道上使用ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
與為該通道引入基於 GTID 的複製不同,您不能對這些通道使用基於 GTID 的複製的交易跳過方法。
若要在跳過交易後重新啟動複製,請執行 START REPLICA
,如果副本是多來源副本,請使用 FOR CHANNEL
子句。
當使用 GTID 時(gtid_mode
為 ON
),即使交易內容被過濾掉,已提交交易的 GTID 也會保存在副本上。此功能可防止副本在使用 GTID 自動定位重新連線至來源時,擷取先前過濾的交易。它也可以用來跳過副本上的交易,方法是提交一個空交易來取代失敗的交易。
如果您使用 CHANGE REPLICATION SOURCE TO
陳述式的 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
選項,在複製通道上啟用了 GTID 指派,則此跳過交易的方法不適用。
如果失敗的交易在工作執行緒中產生錯誤,您可以直接從效能架構(Performance Schema)的 replication_applier_status_by_worker
表格中的 APPLYING_TRANSACTION
欄位取得其 GTID。若要查看交易的內容,請在副本上執行 SHOW RELAYLOG EVENTS
,或在來源上執行 SHOW BINLOG EVENTS
,並在輸出中搜尋以該 GTID 開頭的交易。
當您評估失敗的交易是否有任何其他適當的動作(如先前所述的安全考量)時,若要跳過該交易,請在副本上提交一個與失敗交易具有相同 GTID 的空交易。例如:
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
BEGIN;
COMMIT;
SET GTID_NEXT='AUTOMATIC';
副本上存在此空交易表示,當您執行 START REPLICA
陳述式以重新啟動複製時,副本會使用自動跳過功能來忽略失敗的交易,因為它看到具有該 GTID 的交易已套用。如果副本是多來源副本,則在提交空交易時不需要指定通道名稱,但在執行 START REPLICA
時則需要指定通道名稱。
請注意,如果在此副本上使用二進位日誌記錄,則如果副本在未來成為來源或主要副本,則空交易會進入複製串流。如果您需要避免這種可能性,請考慮清除和清除副本的二進位日誌,如本範例所示:
FLUSH LOGS;
PURGE BINARY LOGS TO 'binlog.000146';
空交易的 GTID 會被保留,但交易本身會透過清除二進位日誌檔案來移除。
若要在未使用 GTID 或正在逐步導入 GTID 時(gtid_mode
為 OFF
、OFF_PERMISSIVE
或 ON_PERMISSIVE
)跳過失敗的交易,您可以透過執行 SET GLOBAL sql_replica_skip_counter
來跳過指定數量的事件。或者,您可以執行 CHANGE REPLICATION SOURCE TO
陳述式來跳過一個或多個事件,將來源二進位日誌位置向前移動。
當您使用 CHANGE REPLICATION SOURCE TO
陳述式的 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
選項,在複製通道上啟用 GTID 指派時,這些方法也適用。
當您使用這些方法時,請務必了解,您不一定會跳過完整的交易,這與先前所述的基於 GTID 的方法的情況始終不同。這些非基於 GTID 的方法不會將交易視為交易,而是對事件進行操作。二進位日誌會組織成稱為事件群組的序列,每個事件群組都由一系列事件組成。
對於交易式表格,事件群組對應於一個交易。
對於非交易式表格,事件群組對應於單個 SQL 陳述式。
單個交易可能包含對交易式和非交易式表格的變更。
當您使用 SET GLOBAL sql_replica_skip_counter
陳述式來跳過事件,並且產生的位置位於事件群組的中間時,副本會繼續跳過事件,直到到達群組的末尾。然後,執行會從下一個事件群組開始。CHANGE REPLICATION SOURCE TO
陳述式沒有此功能,因此您必須小心識別正確的位置,以便在事件群組的開頭重新啟動複製。然而,使用 CHANGE REPLICATION SOURCE TO
表示您不必像使用 SET GLOBAL sql_replica_skip_counter
那樣計算需要跳過的事件,而是可以只指定重新啟動的位置。
當您評估失敗的交易是否有任何其他適當的動作(如先前所述的安全考量)時,請計算您需要跳過的事件數量。一個事件通常對應於二進位日誌中的一個 SQL 陳述式,但請注意,使用 AUTO_INCREMENT
或 LAST_INSERT_ID()
的陳述式在二進位日誌中算作兩個事件。當使用二進位日誌交易壓縮時,壓縮的交易酬載(Transaction_payload_event
)算作單一計數器值,因此其中的所有事件都會作為一個單位跳過。
如果您要跳過完整的交易,您可以將事件計數到交易結束,或者您可以只跳過相關的事件群組。請記住,使用 SET GLOBAL sql_replica_skip_counter
時,副本會繼續跳到事件群組的末尾。請確保您沒有跳過太遠,進入下一個事件群組或交易,以至於它也被跳過。
請依以下方式執行 SET
陳述式,其中 N
是要從來源跳過的事件數:
SET GLOBAL sql_replica_skip_counter = N
如果已設定 gtid_mode=ON
,或複製 I/O(接收器)和 SQL(應用程式)執行緒正在執行,則無法執行此陳述式。
SET GLOBAL sql_replica_skip_counter
陳述式不會立即生效。當您在此 SET
陳述式之後,下次發出 START REPLICA
陳述式時,系統變數 sql_replica_skip_counter
的新值才會被套用,並且會略過事件。該 START REPLICA
陳述式也會自動將系統變數的值設回 0。如果複本是多來源複本,當您發出該 START REPLICA
陳述式時,則必須使用 FOR CHANNEL
子句。請務必指定正確的通道,否則會在錯誤的通道上略過事件。
當您已如先前所述評估失敗的交易是否有任何其他適當的動作(例如安全性考量)時,請找出來源二進位日誌中代表適合重新啟動複製的位置的座標(檔案和位置)。這可以是導致問題的事件之後的事件群組的開始,或下一個交易的開始。下次執行緒啟動時,複製 I/O(接收器)執行緒會從來源的這些座標開始讀取,略過失敗的事件。請務必準確識別位置,因為此陳述式不考量事件群組。
請如下發出 CHANGE REPLICATION SOURCE TO
陳述式,其中 source_log_name
是包含重新啟動位置的二進位日誌檔案,而 source_log_pos
是代表二進位日誌檔案中重新啟動位置的數字
CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='source_log_name', SOURCE_LOG_POS=source_log_pos;
如果複本是多來源複本,您必須在 CHANGE REPLICATION SOURCE TO
陳述式上使用 FOR CHANNEL
子句來命名適當的通道。
如果 SOURCE_AUTO_POSITION
為 1
,或複製 I/O(接收器)和 SQL(套用器)執行緒正在執行,則無法發出此陳述式。如果您需要在 SOURCE_AUTO_POSITION=1
時使用此方法來略過交易,您可以在發出陳述式時將設定變更為 SOURCE_AUTO_POSITION=0
,然後再將其變更回原狀。例如
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=0, SOURCE_LOG_FILE='binlog.000145', SOURCE_LOG_POS=235;
CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION=1;