首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL GTID 複制協議深度解析:新舊協議差異、跳過事務與錯誤事務處理

     編輯:MySQL 資料庫相關知識

MySQL 5.6 引入全局事務 ID (GTID),不僅簡化了主從切換(無需手動找 binlog position),更引入了全新的複制協議。本文對比新舊協議核心差異,詳細講解 sql_slave_skip_counter 失效原因、GTID 下跳過事務正確姿勢、錯誤事務導致的故障轉移風險與規避方案。

一、新舊複制協議核心差異

維度舊協議新協議 (GTID)
從庫請求CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=123發送已執行 GTID 集合:GTID_SET = 'uuid:1-100'
主庫響應從指定位置順序發送所有事務計算差集,僅發送從庫缺失的事務
幂等性無(重複執行風險)嚴格保證 每個 GTID 在從庫僅執行一次

二、實戰場景:缺失事務自動補全

假設從庫缺失事務 2,但請求從事務 4 開始:

  • 舊協議:主庫從 4 開始發送,事務 2 永不補全 → 數據不一致。
  • 新協議:主庫比對 GTID 集合,發現 2 缺失 → 自動補發事務 2 → 數據自動收斂一致。

這是 GTID 協議「以集合為基準、按需補全」設計的核心價值。

三、跳過事務:sql_slave_skip_counter 為何失效?

舊版 SET GLOBAL sql_slave_skip_counter = N 在 GTID 模式下禁止使用。原因:

  1. 新協議基於 GTID 集合交換,主庫會強制發送從庫缺失的 GTID。
  2. 若跳過的事務仍在主庫 binlog 中 → 被重新發送 → 又執行了一次(違背跳過意圖)。
  3. 若已被 Purge → 主庫報錯 1236: master has purged binary logs containing GTIDs that the slave requires → 複制中斷。

正確姿勢:注入空事務佔位

SET gtid_next = 'uuid:N';  -- 要跳過的 GTID
BEGIN; COMMIT;             -- 空事務
SET gtid_next = 'AUTOMATIC';

從庫記錄「已執行該 GTID」,主庫比對集合時視為已同步,不再發送原事務。

四、錯誤事務:從庫本地寫入導致的故障轉移災難

場景:從庫 S1 曾本地執行 CREATE DATABASE mydb;(未寫 binlog 或已 Purge),主庫 M 執行 CREATE DATABASE IF NOT EXISTS mydb;。

故障轉移 S2 → S1 時:

  • S1 向 S2 宣告已執行 GTID 集合(含本地事務)。
  • S2 請求同步,S1 發送本地事務 CREATE DATABASE mydb;。
  • S2 執行報錯 1007: Can't create database 'mydb'; database exists → 複制中斷。

更隱蔽的災難:本地事務已 Purge

  • S1 執行本地事務 → FLUSH LOGS; PURGE BINARY LOGS TO ... 導致該 GTID 不在 binlog。
  • S2 故障轉移至 S1 → 請求缺失 GTID → S1 無法提供 → 報錯 1236 → 永久中斷。

五、規避方案:嚴禁從庫業務寫入

  1. 只讀強制:SET GLOBAL super_read_only=ON;(5.7.8+),防止誤寫入。
  2. 必要本地操作關閉 binlog:SET SESSION sql_log_bin=0; -- 執行 DDL/維護 -- SET SESSION sql_log_bin=1;
  3. 監控告警:監控 Seconds_Behind_Master、Slave_SQL_Running_State、gtid_executed 與主庫差集。

六、總結

GTID 新協議通過「集合比對 + 缺失補全」實現了自動收斂一致,但也帶來了新約束:嚴禁從庫獨立寫入、跳過事務需注入空事務、Purge 需謹慎評估從庫 GTID 需求。理解協議本質,才能在架構變更、故障轉移、版本升級中游刃有餘。

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