雙主(Master-Master)架構讓兩台 MySQL 互為主從,實現寫入高可用與讀寫分離。但雙向複寫天然存在 自增 ID 衝突、複寫延遲、死鎖循環 等隱患。本文以 Ubuntu 12.04 + MySQL 5.1 為例,給出生產級部署步驟、關鍵參數與規避策略。
server-id 唯一-- Node A (192.168.1.2) 授權給 Node B GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.3' IDENTIFIED BY 'StrongPass#2024'; FLUSH PRIVILEGES; -- Node B (192.168.1.3) 授權給 Node A GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.2' IDENTIFIED BY 'StrongPass#2024'; FLUSH PRIVILEGES;
[mysqld] server-id = 1 # Node A=1, Node B=2,必須唯一 log-bin = mysql-bin binlog_format = ROW # ROW 格式避免非確定性函數導致不一致 relay-log = relay-bin relay-log-index = relay-bin.index expire_logs_days = 7 max_binlog_size = 500M # 自增偏移與步長:防止雙主寫入主鍵衝突(核心!) auto_increment_offset = 1 # Node A=1, Node B=2 auto_increment_increment = 2 # 兩節點均設 2 # 指定同步/忽略庫表(按需) replicate-do-db = biz_db replicate-ignore-table = biz_db.big_log_table # 複寫超時與重試 slave_net_timeout = 30 master_connect_retry = 30
Node A 做主,Node B 做從:
-- Node A 鎖表獲取座標 FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS; -- 記下 File (如 mysql-bin.000003) 和 Position (如 73) UNLOCK TABLES; -- Node B 配置主庫資訊並啟動 CHANGE MASTER TO MASTER_HOST='192.168.1.2', MASTER_USER='repl_user', MASTER_PASSWORD='StrongPass#2024', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=73; START SLAVE;
Node B 做主,Node A 做從: 同理執行對稱操作。
SHOW SLAVE STATUS\G -- 關鍵指標均為 Yes Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0
| 坑點 | 後果 | 規避方案 |
|---|---|---|
| 自增主鍵衝突 | 雙邊寫入同一張表產生重複 PK,複寫中斷 | 強制設定 auto_increment_increment=2 + offset=1/2;或改用 UUID/雪花算法主鍵 |
| 循環複寫風暴 | A→B→A 無限循環,Binlog 暴增 | 設定 log_slave_updates=OFF(預設 OFF),或在 CHANGE MASTER 指定 IGNORE_SERVER_IDS (5.7+) |
| 複寫延遲大 | 讀從庫拿到舊數據,業務邏輯錯誤 | 優化慢查詢、升級 SSD、啟用並行複寫 (slave_parallel_workers)、監控 Seconds_Behind_Master 報警 |
| DDL 鎖表阻塞複寫 | 大表 ALTER 導致從庫 SQL 執行緒卡住 | 使用 pt-online-schema-change / gh-ost 線上變更,避免鎖表 |
| 雙邊同時寫入同一行 | 最後提交勝出,資料悄悄不一致 | 業務層路由:同一業務主體(用戶/訂單)固定寫入同一節點;或引入 Proxy(ProxySQL)按分片路由 |