MySQL 主從復制(Replication)是其最核心的高可用性和擴展性功能之一。它的原理是將一個 MySQL 實例(稱為主庫 Master)的數據變更,自動同步到另一個或多個 MySQL 實例(稱為從庫 Slave)的過程。
下面我將詳細解析其工作原理、核心組件和流程。
一、 核心架構與組件
MySQL 主從復制是一個 “異步” 的、基于日志的復制系統,主要涉及三個線程和兩種日志:
角色 | 組件 | 說明 |
主庫 (Master) | Binary Log (binlog) | 核心。記錄所有對數據庫結構和內容進行修改的 SQL 語句(或實際數據行變更)。 |
Binlog Dump Thread | 主庫上的一個線程,負責讀取 binlog 并將其發送給從庫的 I/O 線程。 | |
從庫 (Slave) | I/O Thread | 從庫上的線程,負責連接主庫,請求和接收 binlog 數據,并將其寫入本地的中繼日志。 |
Relay Log | 從庫上的一個日志文件,作為主庫 binlog 的臨時中轉站和緩沖區。 | |
SQL Thread | 從庫上的線程,負責讀取中繼日志中的內容,并解析執行其中的 SQL 語句,最終使從庫數據與主庫保持一致。 |
二、 主從復制的工作原理(三步流程)
整個過程可以清晰地分為三個步驟,下圖直觀地展示了這一流程:
flowchart TD
A[Client Write Request] --> B[Master Database]subgraph Master[Master Server]B --> C[Write Data<br>Update/Insert/Delete]C --> D[Write Binary Log<br>[binlog]]D --> E[Binlog Dump Thread]
endE -- "Binlog Events" --> F[I/O Thread]subgraph Slave[Slave Server]F --> G[Write Relay Log<br>[relay log]]G --> H[SQL Thread]H --> I[Replay Events]I --> J[Slave Data Updated]
end
步驟一:主庫記錄二進制日志 (Binary Log)
- 應用程序向主庫發起數據變更請求(如 ?
?INSERT?
?, ??UPDATE?
?, ??DELETE?
?)。 - 主庫執行完這些事務后,并不會立即返回,而是將這些更改事件按照一定的格式(?
?STATEMENT?
?, ??ROW?
?, ??MIXED?
?)寫入到自己的 Binary Log 文件中。
- 注意:只有寫操作會被記錄,讀操作不會。
步驟二:從庫請求并接收日志 (I/O Thread)
- 從庫的 I/O 線程會啟動一個到主庫的客戶端連接。
- I/O 線程向主庫的 Binlog Dump 線程發送一個請求,指定從哪個 binlog 文件的哪個位置開始同步。
- 主庫的 Binlog Dump 線程讀取 binlog 內容,并通過之前建立的連接發送給從庫。
- 從庫的 I/O 線程接收到這些 binlog 事件后,會將其順序地寫入到本地的 Relay Log 文件中。
步驟三:從庫重放中繼日志 (SQL Thread)
- 從庫的 SQL 線程會不斷地讀取 Relay Log 文件中的事件。
- SQL 線程會解析并執行這些事件中的 SQL 語句(或者在 ?
?ROW?
? 格式下,直接應用數據行的變化),從而在從庫上重現主庫上的操作。 - 一旦 SQL 線程執行完一個事件,它就會更新自己的 ?
?master.info?
? 和 ??relay-log.info?
? 文件,記錄當前讀取到的主庫 binlog 位置,以便中斷后能從正確的位置繼續復制。
總結來說,從庫通過兩個線程實現了“接收日志”和“執行日志”的解耦:I/O 線程負責從主庫拉取數據,SQL 線程負責消費這些數據。Relay Log 作為中間的緩沖區,使得兩個線程可以獨立工作,提高了復制的效率和穩定性。
三、 復制的格式 (Binlog Format)
這是理解復制行為和排查問題的關鍵。主庫記錄 binlog 有三種格式:
格式 | 原理 | 優點 | 缺點 |
STATEMENT (SBR) | 記錄原始的 SQL 語句。 | 日志文件小,節省磁盤和網絡 I/O。 | 可能因上下文信息(如系統變量、觸發器)導致主從數據不一致。 |
ROW (RBR) | 記錄每行數據如何被修改(修改前鏡像/修改后鏡像)。 | 安全可靠,幾乎可以保證主從數據絕對一致。這是默認推薦的格式。 | 日志文件大(例如一條 ? |
MIXED (MBR) | 混合模式。一般情況下使用 STATEMENT,但在可能造成不一致的場景下(如使用 ? | 兼顧了安全性和性能。 | 仍存在極小的不確定性。 |
四、 半同步復制 (Semi-Synchronous Replication)
上述默認的復制是完全異步的。這意味著:
- 主庫提交事務并寫入binlog后,立即返回給客戶端成功。
- binlog 通過異步的方式發送給從庫。
風險:如果主庫在返回成功后、binlog還未發送到任何從庫時就宕機了,雖然客戶端認為成功了,但這個事務實際上丟失了。
半同步復制 為了解決這個問題而誕生:
- 主庫在提交事務時,會等待至少一個從庫的 I/O 線程確認已經接收到了這個事件的 binlog。
- 只有在收到確認后,主庫才會返回成功給客戶端。
- 如果超時(可配置)還未收到確認,復制會降級為異步模式,之后一旦有從庫恢復,又會自動升級回半同步。
這就在性能和數據一致性之間提供了一個很好的折衷,確保了數據的冗余性。
五、 主從復制的應用場景
- 讀寫分離:主庫處理寫操作和實時性要求高的讀操作,從庫處理大量的分析報表類讀操作,顯著提升系統整體性能。
- 數據備份:在從庫上進行備份,不會對主庫造成任何壓力。
- 高可用性和故障切換:主庫宕機后,可以快速將一個從庫提升為新的主庫,減少系統停機時間。
- 地理分布:將數據同步到不同地理位置的從庫,供當地用戶訪問,提升訪問速度。
六、 總結與核心要點
- 基礎原理:基于 Binlog,采用 “拉” 的異步模式。
- 三個線程:主庫的 Binlog Dump,從庫的 I/O 和 SQL。
- 兩個日志:主庫的 Binary Log,從庫的 Relay Log。
- 核心流程:主庫寫Binlog -> 從庫I/O線程拉取并寫Relay Log -> 從庫SQL線程重放Relay Log。
- 格式選擇:推薦使用 ROW 格式,以保證數據一致性。
- 數據安全:對數據可靠性要求極高的場景,可使用半同步復制。
另外搭配便捷的MYSQL備份工具,可定時備份、異地備份,MYSQL導出導入。可本地連接LINUX里的MYSQL,簡單便捷。可以大大地提高工作效率喔。