MySQL 複寫模式決定了資料一致性與可用性的權衡。異步複寫延遲低但可能丟資料;半同步複寫引入 ACK 機制大幅降低丟資料風險,但增加延遲。本文詳細剖析兩種模式的底層流程、部署步驟、參數調優、監控指標與生產選型建議。
主庫 Commit 後**立即返回給客戶端**,不等待從庫 ACK。網路抖動、從庫宕機會導致主庫已提交事務從庫未收到 → **資料丟失風險**。
| 優點 | 缺點 |
|---|---|
| 延遲極低,主庫效能無損 | 主庫故障切換時,未同步事務永久丟失 |
| 架構簡單,無額外元件 | 無法保證 RPO=0 |
# Master my.cnf [mysqld] server_id=1 log_bin=mysql-bin binlog_format=ROW gtid_mode=ON enforce_gtid_consistency=ON # Slave my.cnf [mysqld] server_id=2 relay_log=relay-bin log_slave_updates=ON read_only=ON # 建立複寫帳號 CREATE USER 'repl'@'%' IDENTIFIED BY 'ReplPassw0rd!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; # Slave 啟動 CHANGE MASTER TO MASTER_HOST='10.0.0.1', MASTER_USER='repl', MASTER_PASSWORD='ReplPassw0rd!', MASTER_AUTO_POSITION=1; START SLAVE;
rpl_semi_sync_master_timeout (預設 10000ms) 未收到 ACK → **自動降級為異步**,避免主庫阻塞。rpl_semi_sync_slave_enabled,ACK 發送機制由 Slave IO Thread 完成。-- Master INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; -- Slave INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
# Master my.cnf rpl_semi_sync_master_enabled=ON rpl_semi_sync_master_timeout=5000 -- 5 秒降級,平衡一致性與可用性 rpl_semi_sync_master_wait_point=AFTER_SYNC -- AFTER_COMMIT/AFTER_SYNC,8.0.26+ 建議 AFTER_SYNC rpl_semi_sync_master_wait_for_slave_count=1 -- 至少 1 個從庫 ACK # Slave my.cnf rpl_semi_sync_slave_enabled=ON
SHOW GLOBAL STATUS LIKE 'Rpl_semi_sync%'; -- 關鍵指標 Rpl_semi_sync_master_status=ON -- 功能啟用 Rpl_semi_sync_master_yes_tx=12345 -- 成功半同步提交數 Rpl_semi_sync_master_no_tx=12 -- 降級異步提交數 Rpl_semi_sync_master_net_wait_time=4500000 -- 總等待微秒數 Rpl_semi_sync_slave_status=ON -- 從庫半同步啟用
| 模式 | TPS | Avg Latency (ms) | 95% Latency (ms) | 降級次數/小時 |
|---|---|---|---|---|
| 異步 | 3600 | 2.5 | 4.2 | 0 |
| 半同步 (timeout=5s, 同機房) | 3200 (-11%) | 3.1 | 6.8 | 0 |
| 半同步 (timeout=5s, 跨可用區 2ms RTT) | 2400 (-33%) | 5.8 | 18.5 | 15 |
結論:同機房部署半同步效能損失 <10%,可接受;跨可用區 RTT >1ms 明顯拖垮主庫,建議改用 **Group Replication (MGR)** 或 **Galera Cluster** 實現同步複寫。
主庫掛掉,從庫提升為新主庫時,舊主庫已提交但未傳送的 binlog 事件永久丟失。
**緩解**:sync_binlog=1、innodb_flush_log_at_trx_commit=1 確保主庫本地不丟;搭配 Orchestrator/MHA 自動切換。
Rpl_semi_sync_master_yes_tx 最大 (最完整)。rpl_semi_sync_master_wait_point=AFTER_SYNC -- 事務在「寫入 binlog 並 fsync」後再等待 ACK,而非 Commit 後。 -- 保證:只要主庫回傳 Commit 成功,該事務必定已在至少一個從庫 Relay Log 持久化。 -- 這是目前單主架構下 RPO=0 的最佳折中方案。
業務能容忍丟資料?
├─ 是 (日誌、統計、可重算) → 異步複寫,簡單高效
└─ 否 (交易、訂單、帳戶)
├─ 同機房部署 → 半同步 (Lossless) + Orchestrator,RPO=0,效能損失 <10%
└─ 多可用區/異地 → Group Replication (單主/多主) 或 Galera Cluster
→ 真正同步複寫,強一致性,但寫入延遲 = 網路 RTT,需應用層容忍
結語: 半同步複寫是「異步效能」與「同步一致性」之間的工程甜點。MySQL 5.7+ 的 Lossless 模式配合 GTID 與 Orchestrator,已能滿足絕多數金融級核心業務的 RPO=0 需求。跨機房強一致場景請直接上 MGR/Galera,不要嘗試拉長半同步 Timeout 硬抗網路延遲。