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

MySQL 主從不同步故障排查實戰:Duplicate Entry 錯誤根因分析與標準化恢復流程

     編輯:MySQL 資料庫相關知識

故障現場還原

  • 現象: 網頁讀取從庫數據為空/報錯
  • Master 狀態: SHOW PROCESSLIST 正常,SHOW MASTER STATUS 正常推進
  • Slave 狀態:
    
        SHOW SLAVE STATUS\G
        Last_Error: Error 'Duplicate entry '1' for key 1' on query. Default database: 'movivi1'. Query: 'INSERT INTO `v1vid0_user_samename` VALUES(null,1,'123','11','4545','123')'
        Slave_SQL_Running: No
        Seconds_Behind_Master: NULL
        

診斷結論: SQL 線程因主鍵衝突停止,IO 線程仍在運行,主從數據已發生分歧。

緊急恢復標準流程 (跳過錯誤事務)


-- 1. 停止 SQL 線程 (IO 線程可選繼續拉取 Binlog)
STOP SLAVE SQL_THREAD;

-- 2. 跳過 1 個導致錯誤的事務 (謹慎!確認業務可接受數據不一致)
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;

-- 3. 啟動 SQL 線程
START SLAVE SQL_THREAD;

-- 4. 監控追趕進度
SHOW SLAVE STATUS\G;
-- 關鍵:Seconds_Behind_Master 從 NULL 變數字,最終趨近 0

⚠️ 風險提示: SQL_SLAVE_SKIP_COUNTER 會跳過**整個事務** (可能包含多條 DML),導致從庫缺失該事務所有變更。生產環境必須:

  1. 確認錯誤事務業務影響 (通過 SHOW BINLOG EVENTS 解析)
  2. 評估數據不一致風險 (核心表不可跳過)
  3. 記錄跳過事務 GTID/位點,事後補償

根因深度分析:為什麼會發生 Duplicate Entry?

根因類別具體場景防範措施
雙主/多寫入應用誤連從庫寫入、雙主未配置 auto_increment_offset/step嚴格只讀從庫:read_only=1, super_read_only=1 (5.7+),應用層路由隔離
手動操作DBA 在從庫直接 INSERT/UPDATE、導入備份數據未去重禁止從庫手動寫入,變更走審批流程,備份導入前 SET SESSION sql_log_bin=0
非幂等重放Slave 重啟/重做時,事務重複執行 (無 GTID 去重)啟用 GTID 複制 (5.6+),gtid_mode=ON, enforce_gtid_consistency=ON
主鍵設計缺陷業務主鍵非自增、分布式 ID 生成衝突、分表邏輯錯誤統一 64 位自增/雪花算法,分表鍵與主鍵分離
Binlog 格式問題STATEMENT 模式下非確定性函數 (NOW/RAND) 導致主從結果不一致強制 binlog_format=ROW (5.7+ 默認)

標準化重搭從庫流程 (數據糾偏終極方案)

當跳過事務風險不可接受、或從庫數據嚴重偏離時,必須重搭:

前提條件

  • Master 正常運行,**不可停機**
  • Master IP: 192.168.1.100,Slave IP: 192.168.1.101
  • 複製賬號:repl_user / StrongPass#2024,權限:REPLICATION SLAVE, RELOAD, SUPER

操作步驟

  1. Master 配置確認 (/etc/my.cnf):
    
        [mysqld]
        server-id=1
        log-bin=mysql-bin
        binlog-format=ROW
        binlog-do-db=business_db  # 白名單
        gtid_mode=ON
        enforce_gtid_consistency=ON
        
  2. Master 創建/驗證複製賬號:
    
        GRANT REPLICATION SLAVE, RELOAD, SUPER ON *.* TO 'repl_user'@'192.168.1.%' IDENTIFIED BY 'StrongPass#2024';
        FLUSH PRIVILEGES;
        
  3. Slave 停止複製並清理舊數據:
    
        STOP SLAVE;
        RESET SLAVE ALL;  -- 5.7.6+ 清除 GTID 執行集、中繼日志、位點
        -- 物理刪除數據目錄 (保留配置)
        rm -rf /var/lib/mysql/*
        
  4. Master 熱備份 (XTRABackup 推薦,無鎖/流式/並行):
    
        # Master 執行
        xtrabackup --backup --target-dir=/backup/full_$(date +%F) --user=root --password=*** --parallel=4 --compress
        xtrabackup --prepare --target-dir=/backup/full_$(date +%F)
        # 傳輸到 Slave (rsync/scp)
        rsync -avz /backup/full_$(date +%F)/ slave:/var/lib/mysql/
        # Slave 權限修正
        chown -R mysql:mysql /var/lib/mysql
        

    備選: mysqldump --single-transaction --master-data=2 --routines --triggers --events --databases business_db | gzip > dump.sql.gz (小數據量 < 50GB)

  5. Slave 啟動並配置複製:
    
        # Slave my.cnf 確認
        [mysqld]
        server-id=2
        gtid_mode=ON
        enforce_gtid_consistency=ON
        relay-log=relay-bin
        log-slave-updates=1
        read_only=1
        super_read_only=1
    
        # 啟動 MySQL
        systemctl start mysqld
    
        # 配置複製 (GTID 模式無需指定文件/位點)
        CHANGE MASTER TO
          MASTER_HOST='192.168.1.100',
          MASTER_USER='repl_user',
          MASTER_PASSWORD='StrongPass#2024',
          MASTER_PORT=3306,
          MASTER_AUTO_POSITION=1;  -- GTID 核心參數
    
        START SLAVE;
        
  6. 驗證同步狀態:
    
        SHOW SLAVE STATUS\G;
        Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
        Seconds_Behind_Master: 0
        Retrieved_Gtid_Set: xxxx-xxxx...
        Executed_Gtid_Set: xxxx-xxxx...  -- 應包含 Retrieved
        
  7. 業務驗證:Master 寫入測試數據 → Slave 秒級可見 → 應用切換讀流量

進階排查工具箱

工具/命令用途
pt-table-checksum / pt-table-syncPercona Toolkit:主從數據一致性校驗與修復 (基於 chunk、不鎖表)
mysqlbinlog --verbose --base64-output=DECODE-ROWS解析 Binlog/Relay Log 還原真實 SQL,定位衝突事務
SHOW BINLOG EVENTS IN 'mysql-bin.000123' FROM 456 LIMIT 10精確定位位點附近事件
performance_schema.replication_applier_status_by_worker5.7+ 並行複製 Worker 級狀態
GTID 集合運算SELECT GTID_SUBTRACT('Executed', 'Retrieved') 找出從庫多執行的事務

預防性架構建設

  1. 強制 ROW 格式 + GTID: 消除非確定性、自動位點管理
  2. 從庫只讀 + 審計: super_read_only=1 + audit_log 記錄所有嘗試寫入
  3. 並行複製 (MTS): slave_parallel_workers=8, slave_parallel_type=LOGICAL_CLOCK (5.7+) 加速追趕
  4. 監控體系: Seconds_Behind_Master、Slave_*_Running、Relay_Log_Space、Last_Error 告警
  5. 定期演練: 季度一次「從庫重搭 + 數據校驗」演練,固化 SOP

總結

主從不同步的核心是「數據分歧」。SQL_SLAVE_SKIP_COUNTER 是**止血針**,重搭從庫 是**根治術**。現代架構必須標配:GTID + ROW + 只讀從庫 + 並行複製 + XtraBackup 熱備 + pt-checksum 校驗。故障處理鐵律:**先保業務可用 (跳過/切主) → 再根因分析 → 最後數據糾偏 (重搭/同步)**。記住:最好的故障處理是預防,最可靠的同步是 GTID,最安全的備份是離線物理備份。

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