架構定位
**雙主雙向複寫**:兩台 MySQL 互為主從,雙向同步寫入。適用於雙活、跨機房高可用、讀寫分離負載均衡。關鍵挑戰:自增 ID 衝突,必須透過 auto_increment_increment / auto_increment_offset 錯開。
雙節點規劃
| 角色 | IP | Server ID | auto_increment_offset | auto_increment_increment |
| Node A | 192.168.3.116 | 1 | 1 | 2 |
| Node B | 192.168.3.115 | 2 | 2 | 2 |
→ Node A 產生奇數 ID (1,3,5...),Node B 產生偶數 ID (2,4,6...),**永不衝突**。
Node A(Master 1)配置
# /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
log-slave-updates=1
relay_log=/var/lib/mysql/mysql-relay-bin
sync_binlog=1
auto_increment_increment=2
auto_increment_offset=1
slave-skip-errors=all
validate_password=OFF
Node B(Master 2)配置
# /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id=2
log-bin=mysql-bin
log-slave-updates=1
relay_log=/var/lib/mysql/mysql-relay-bin
sync_binlog=1
auto_increment_increment=2
auto_increment_offset=2
slave-skip-errors=all
validate_password=OFF
關鍵參數解析
| 參數 | 作用 | 建議值 |
log-slave-updates | 將從庫回放的事務再寫入自身 Binlog,**雙向複寫必開** | 1 |
sync_binlog=1 | 每次提交刷盤,保證 Binlog 不丟失(犧牲些許效能換數據安全) | 1 |
slave-skip-errors=all | 複寫報錯自動跳過(慎用!建議改為具體錯誤碼如 1062) | 1062,1032 |
auto_increment_increment/offset | 錯開自增 ID,防雙主寫入衝突 | 見上表 |
建立複寫帳號(雙向各執行一次)
-- Node A 執行,授權 Node B 連線
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.3.115' IDENTIFIED BY 'zcxc123';
FLUSH PRIVILEGES;
-- Node B 執行,授權 Node A 連線
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.3.116' IDENTIFIED BY 'zcxc123';
FLUSH PRIVILEGES;
初始化同步流程(冷備份法)
- Node A 鎖表備份:
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS; -- 記錄 File/Position
mysqldump -uroot -p --all-databases --master-data=2 --single-transaction > /tmp/all_db.sql
UNLOCK TABLES;
- 傳輸並導入 Node B:
scp /tmp/all_db.sql root@192.168.3.115:/tmp/
mysql -uroot -p < /tmp/all_db.sql
- Node B 配置複寫指向 Node A:
RESET SLAVE;
CHANGE MASTER TO
MASTER_HOST='192.168.3.116', MASTER_USER='repl_user', MASTER_PASSWORD='zcxc123',
MASTER_LOG_FILE='mysql-bin.000080', MASTER_LOG_POS=154;
START SLAVE;
- Node A 配置複寫指向 Node B(同理,用 Node B 的 Binlog 位置)
驗證雙向同步
-- Node A 執行
CREATE DATABASE test_db;
CREATE TABLE test_db.t1 (id INT PRIMARY KEY AUTO_INCREMENT, v VARCHAR(20));
INSERT INTO test_db.t1 (v) VALUES ('from A');
-- Node B 查詢
SHOW DATABASES LIKE 'test_db';
SELECT * FROM test_db.t1; -- 應看到 id=1 (奇數)
-- Node B 執行
INSERT INTO test_db.t1 (v) VALUES ('from B');
-- Node A 查詢
SELECT * FROM test_db.t1; -- 應看到 id=2 (偶數)
常見坑點與對策
| 問題 | 原因 | 對策 |
| 自增 ID 衝突 | 未設定 increment/offset | 強制配置錯開,或改用 UUID/GUID |
| 循環複寫 | 缺少 log-slave-updates 或 replicate-same-server-id=0 | 啟用 log-slave-updates,預設 replicate-same-server-id=0 已防循環 |
| 雙寫衝突(同一行同時更新) | 應用層未分片/路由 | 業務層保證單主寫入,或用 Galera Cluster/PXC 實現多主同步 |
| Binlog 格式不一致 | 一邊 ROW 一邊 STATEMENT | 雙邊統一 binlog_format=ROW |
| 從庫落後無法追上 | 單線程回放、大事務、無索引更新 | 開啟並行複寫 SLAVE_PARALLEL_TYPE=LOGICAL_CLOCK |
監控指標
Seconds_Behind_Master 兩向皆 < 1 秒
SHOW SLAVE STATUS\G 無 Last_SQL_Error
- Binlog 磁碟增長速率正常(無暴增)
- 定期
pt-table-checksum 驗證數據一致性
copyright ©
萬盛學電腦網 all rights reserved