概述
MySQL Replication(復制)是一個異步過程,將 Master 實例的數據變更複製到一個或多個 Slave 實例。整個過程由三個線程協作完成:
- Master IO 線程:負責讀取 Binlog 發送給 Slave。
- Slave IO 線程:連接 Master,請求 Binlog,寫入本地 Relay Log。
- Slave SQL 線程:讀取 Relay Log,解析並重放 SQL 語句。
前置條件:開啟 Binlog
Master 必須啟用 Binary Log(--log-bin 或 my.cnf 中 log-bin),否則無法復制。Binlog 記錄所有修改數據的操作(含事務信息、執行時間等),是復制的數據源。
復制全流程詳解
- Slave IO 線程連接 Master,請求從指定 Binlog 文件及位置(或最開始)之後的日志內容。
- Master IO 線程 根據請求讀取 Binlog,返回給 Slave IO 線程。返回內容包含:日志事件、當前 Binlog 文件名、位置(用於下次請求斷點續傳)。
- Slave IO 線程 將接收到的事件順序寫入本地 Relay Log(
mysql-relay-bin.xxxxxx),並將 Master 的 Binlog 文件名和位置記錄到 master.info 文件。
- Slave SQL 線程 檢測到 Relay Log 新增內容,解析為 Master 端原始可執行 Query,在 Slave 端順序執行。至此,Master/Slave 數據邏輯一致。
為什麼從單線程演進為雙線程?
早期版本 Slave 端僅一個線程串行完成「拉取 Binlog → 解析 → 執行」。存在兩大弊端:
- 性能瓶頸:拉取、解析、執行串行,Replication 延遲大。
- 數據丟失風險:Slave 解析/執行期間,Master 可能產生大量新 Binlog。若此時 Master 存儲故障,這段增量數據永久丟失。Slave 壓力越大,解析執行越慢,潛在丟失窗口越大。
Yahoo! 工程師 Jeremy Zawodny 提出雙線程改造:IO 線程專職拉取寫 Relay Log,SQL 線程專職重放。這極大縮短了異步延遲,並減小了不可恢復數據丟失窗口(僅限於 Master Binlog 未傳至 Slave Relay Log 的部分)。
遺留風險與總結
即使雙線程協作,異步復制本質未變:
- Slave 延遲不可避免(網絡、負載、大事務等)。
- 非事務內的跨表/跨庫操作仍可能導致數據不一致。
- 若需強一致性,需配合半同步復制或 GTID + 多線程復制(MySQL 5.6+)。
本文梳理了主從同步的基礎原理、三線程協作流程及演進動機,為後續高可用架構(MHA、MGR 等)奠定基礎。