首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL GTID 複制協議深度解析:新協議如何解決舊協議跳過事務、錯誤事務難題

     編輯:MySQL 綜合教學

MySQL GTID 複制協議深度解析

MySQL 5.6 引入全局事務 ID (GTID) 不僅簡化了故障切換,更引入了全新的**複制協議**。本文對比新舊協議差異,揭示為何 sql_slave_skip_counter 失效、錯誤事務 (Erroneous Transaction) 會導致嚴重後果,並給出正確處理姿勢。

新舊協議核心差異

維度舊協議 (檔案+位置)新協議 (GTID 集合)
同步起點MASTER_LOG_FILE + MASTER_LOG_POS從庫發送 已執行 GTID 集合
主庫動作從指定位置順序發送事務計算差集,**發送從庫缺失的每個 GTID 事務**
冪等性無保證,重複執行風險**嚴格保證**:每個 GTID 在從庫**只執行一次**

場景一:跳過事務 —— 為何 sql_slave_skip_counter 廢用?

舊協議下,SET GLOBAL sql_slave_skip_counter = 1 讓 SQL 線程跳過下一個事務。但在 GTID 協議下:

  1. 從庫重連新主庫時,雙方交換已執行 GTID 集合。
  2. 新主庫發現從庫缺少某 GTID (因跳過而未執行),**會自動重發該事務**。
  3. 若該事務仍在主庫 Binlog 中 → 從庫再次執行,**跳過失效**;若已 purge → **複制報錯中斷** (Error 1236)。

正解:注入空事務佔位

SET GTID_NEXT = 'aaa-bbb-ccc:5';  -- 要跳過的 GTID
BEGIN; COMMIT;                     -- 空事務
SET GTID_NEXT = 'AUTOMATIC';       -- 恢復自動分配

此法讓 GTID 集合完整,新主庫不再重發,複制鏈路穩定。

場景二:錯誤事務 —— 從庫誤執行本地寫入的災難

若從庫直接執行寫入 (如手動 CREATE DATABASE),產生本地 GTID (錯誤事務)。後續將該從庫提升為主庫,或掛載到新主庫下:

  • 舊協議: 數據不一致但複制不中斷,隱患極大。
  • 新協議: 新主庫檢測到從庫有「額外 GTID」,視為缺失事務,**強制重放** → 衝突報錯 (如 Error 1007: Database exists) 或找不到 Binlog 報 1236,**複制直接中斷**。

兩大經典失敗案例

# 案例 1:主庫用 IF NOT EXISTS 避開衝突,但從庫無此保護
S1: CREATE DATABASE mydb;           -- 產生 GTID 100
M:  CREATE DATABASE IF NOT EXISTS mydb; -- 不產生新 GTID (或產生不同 GTID)
S2 -> S1: 複制衝突,報 1007

# 案例 2:錯誤事務 Binlog 被清理
S1: CREATE DATABASE mydb; FLUSH LOGS; PURGE BINARY LOGS TO 'bin.000008'; -- GTID 100 被刪
M:  CREATE DATABASE IF NOT EXISTS mydb;
S2 -> S1: 缺少 GTID 100 且主庫無 Binlog,報 1236 致命錯誤

最佳實踐:杜絕錯誤事務

  1. 嚴禁從庫直接寫入 (設置 read_only=ON、super_read_only=ON)。
  2. 必須在從庫執行管理操作時: 臨時關閉 Binlog 記錄:
    SET SESSION SQL_LOG_BIN = 0;
    -- 執行 DDL/DML
    SET SESSION SQL_LOG_BIN = 1;
  3. 監控異常 GTID: 定期比對 SHOW MASTER STATUS 與 SHOW SLAVE STATUS 的 Executed_Gtid_Set。

結語: GTID 新協議以「嚴格冪等」換取運維簡易,代價是**零容忍錯誤事務與手動跳過**。理解協議本質,才能駕馭 GTID 強大威力而不踩坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved