前言
MySQL 主主複製 (雙向同步) 允許兩個節點互為主從,**雙寫**同步,常用於雙活架構、異地災備、讀寫分離主備切換。但**雙寫衝突風險極高** (自增 ID 衝突、唯一鍵衝突、事務隔離級別差異)。本文詳細記錄基於 Binlog (Position/GITD) 的搭建步驟、關鍵參數配置、衝突預防策略、監控運維及現代替代方案。
一、 架構與核心參數規劃
| 節點 | IP | Server ID | 角色 | 關鍵配置 |
| Node A | 192.168.0.1 | 1 | Master / Slave | log_bin, binlog_do_db, auto_increment_offset=1, auto_increment_increment=2 |
| Node B | 192.168.0.2 | 2 | Master / Slave | log_bin, binlog_do_db, auto_increment_offset=2, auto_increment_increment=2 |
二、 核心配置文件 (my.cnf) - 關鍵差異化參數
Node A (192.168.0.1)
[mysqld]
server-id = 1
log-bin = /var/log/mysql/mysql-bin
binlog-format = ROW # 強烈推薦 ROW 格式,減少衝突、支持幂等
binlog-do-db = business_db # 只同步業務庫
binlog-ignore-db = mysql,sys,performance_schema,information_schema
# === 雙主防衝突核心 ===
auto_increment_increment = 2 # 自增步長
auto_increment_offset = 1 # 起始偏移 (生成 1,3,5,7...)
# 從庫相關 (作為 B 的從庫)
relay-log = /var/log/mysql/relay-bin
log-slave-updates = 1 # **關鍵**!將從庫執行的事件寫入自己的 Binlog,傳遞給下游
read-only = 0 # 雙主雙寫需開寫 (但應用層路由控制)
# slave-skip-errors = 1062 # 危險!生產禁用,掩蓋衝突
# GTID 模式 (5.6+ 推薦)
gtid_mode = ON
enforce_gtid_consistency = ON
Node B (192.168.0.2) - 差異行高亮
server-id = 2
auto_increment_offset = 2 # 生成 2,4,6,8... **與 A 錯開**
# 其他參數同 A (log_bin 路徑、binlog_do_db 等)
三、 搭建步驟 (基於 GTID 模式,5.6+ 標準流程)
1. 準備雙向同步賬號
-- Node A 執行 (授權給 B 連接)
CREATE USER 'repl'@'192.168.0.2' IDENTIFIED BY 'ReplPass#2024!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.2';
-- Node B 執行 (授權給 A 連接)
CREATE USER 'repl'@'192.168.0.1' IDENTIFIED BY 'ReplPass#2024!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.1';
2. 獲取同步起點 (GTID 模式無需手動獲取 File/Position)
若為全新實例或已同步一致,直接配置源即可。若有既有數據差異,需先全量同步 (XtraBackup/Clone Plugin) 確保數據一致再建立複製。
3. 配置複製源並啟動
-- Node A (作為 B 的從庫)
CHANGE MASTER TO
MASTER_HOST = '192.168.0.2',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplPass#2024!',
MASTER_AUTO_POSITION = 1; -- GTID 模式核心參數
START SLAVE;
-- Node B (作為 A 的從庫)
CHANGE MASTER TO
MASTER_HOST = '192.168.0.1',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'ReplPass#2024!',
MASTER_AUTO_POSITION = 1;
START SLAVE;
4. 驗證狀態
SHOW SLAVE STATUS\G
-- 關鍵指標均為 Yes:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
-- GTID 模式下:
Retrieved_Gtid_Set: xxxx
Executed_Gtid_Set: xxxx
Auto_Position: 1
四、 雙寫衝突預防:生存法則
| 衝突類型 | 風險 | 預防方案 |
| 自增主鍵衝突 | 極高 | 強制配置 auto_increment_increment=2 + offset=1/2 (見上)。UUID/雪花算法更佳。 |
| 唯一鍵衝突 (業務鍵) | 高 | 應用層路由:**同一業務實體 (用戶/訂單) 強制路由到同一節點寫入** (Sharding Key)。避免雙寫同一實體。 |
| DELETE/UPDATE 衝突 | 中 | Row 格式 Binlog 記錄前後圖,從庫執行時按主鍵定位,若行不存在/已修改報錯。需業務保證不並發修改同一行。 |
| DDL 衝突 | 高 | **禁止雙邊並發 DDL**。變更流程:單邊執行 → 等待同步完成 → 另一邊驗證。 |
| 觸發器/存儲過程副作用 | 中 | 從庫 log_slave_updates=1 會重放,避免非幂等邏輯 (如發郵件、調用外部 API)。 |
五、 監控與運維關鍵指標
-- 1. 延遲監控 (秒)
Seconds_Behind_Master
-- 2. GTID 集合一致性
SELECT @@GLOBAL.GTID_EXECUTED; -- 兩節點對比
-- 3. 錯誤檢測
Last_IO_Error, Last_SQL_Error
-- 4. Relay Log 空間
Relay_Log_Space
-- 5. 自動化巡檢腳本 (Prometheus + mysqld_exporter 告警規則)
- alert: MySQLReplicationLag
expr: mysql_slave_status_seconds_behind_master > 30
- alert: MySQLReplicationDown
expr: mysql_slave_status_slave_io_running == 0 or mysql_slave_status_slave_sql_running == 0
六、 常見故障處理
- SQL 線程報錯 1062 (Duplicate Entry):
- 原因:雙寫衝突或手動操作導致。
- 處理:嚴禁
slave_skip_errors=1062。需對比數據、修復不一致、重做同步 (或 GTID 注入空事務跳過)。
- IO 線程斷開 (連接超時/網絡抖動):
- 檢查防火牆、網絡、
slave_net_timeout (默認 60s,建議 10-30s)、master_retry_count。
- GTID 模式自動斷點續傳,無需手動干預 File/Position。
- Binlog 文件丟失 (Master 清理過快):
- 增大
expire_logs_days (如 7-14 天) 或 binlog_expire_logs_seconds (8.0)。
- 從庫需
relay_log_purge=1 (默認) 自動清理已應用 Relay Log。
七、 現代替代方案:為什麼生產環境少用雙主?
| 方案 | 架構 | 優勢 | 適用場景 |
| MGR (MySQL Group Replication) / InnoDB Cluster | 多主 / 單主 Paxos 協議 | 原生高可用、自動故障轉移、一致性強、無衝突 (認證機制)、讀寫分離 Router | **核心業務首選**,3+ 節點 |
| Galera Cluster (PXC / MariaDB) | 多主 同步複製 (wsrep) | 同步強一致、多寫無衝突 (認證)、熱擴展 | 高可用、多寫需求、可容忍延遲 |
| 單主 + 多從 + ProxySQL/Orchestrator/MHA | 單寫 異步/半同步 | 架構簡單、無衝突風險、工具成熟 | 絕大多數 OLTP 業務 |
| 雙主 (本文方案) | 雙寫 異步 | 部署簡單、雙活讀寫 | **非核心、低併發、業務可強制分片路由** |
八、 總結
MySQL 雙主複製**技術上可行、工程上危險**。核心在於 auto_increment_offset/increment 錯開自增 ID、**應用層強制分片路由避免雙寫衝突**、binlog_format=ROW + log_slave_updates=1 保證傳遞鏈路完整、**GTID 模式簡化運維**。**強烈建議核心業務遷移至 MGR (InnoDB Cluster) 或 Galera Cluster 獲得原生多主強一致保障**。若必須用雙主,請建立完善的衝突監控、數據一致性校驗 (pt-table-checksum) 和應急預案。
- 上一篇文章: MySQL InnoDB 調大 innodb_log_file_size 導致啟動失敗:原理、正確變更流程與避坑指南
- 下一篇文章: MySQL 核心參數調優全攻略:五大類別三十餘關鍵參數系統化配置指南
Copyright ©
程式碼之家 All Rights Reserved