複制解決的問題
1.備份容災
不同備庫分布在不用的地理位置,實體隔絕,可以用來備份資料和容災
2.負載均衡
複制可以将多個讀操作分布到不用的備庫伺服器,實作對讀密集型應用的優化
3.高可用性能和故障切換
複制能避免MySQL單點故障,某個節點發生當機,可以快速記性故障切換,提高系統高可用性
4.MySQL更新測試
這種做法較普遍,使用一個更高版本的MySQL作為備庫,保證在更新全部執行個體前,查詢能正常在其他備庫上進行
複制如何工作
複制有三個步驟:
1.在主庫上把更改記錄到二進制日志(Binary Log)中(這些記錄被稱為二進制日志事件)
2.備庫将主庫上的日志複制到自己的中繼日志(Relay Log)中
3.備庫讀取中繼日志中的事件,将其重放到備庫資料庫
下圖更較長的描述複制的細節:
第一步中,每次準備送出事務完成資料更新前,主庫将資料更新的事件記錄到二進制日志中,完了才會一起送出事務,是以不用擔心資料更新了,但是二進制日志更新卻失敗的情況出現
下一步,備庫會啟動一個I/O線程和主庫建立連接配接,主庫上啟動一個特殊的二進制轉儲(binlog dump)線程讀取二進制日志中的事件,備庫I/O線程會将接收到的事件記錄到中繼日志中
最後一步,備庫的SQL線程重中繼日志中讀取事件并在備庫上執行,進而實作資料更新
複制的原理
基于語句的複制
在MySQL5.0及之前的版本隻支援基于語句的複制(也稱為邏輯複制)。這種複制模式下,主庫會記錄資料更改的語句,備庫将這些更改語句再執行一遍完成複制,這樣做有好處也有壞處
好處:
- 實作簡單
- 節省帶寬空間,一條更新好幾兆資料的語句在一個二進制日志裡可能隻有幾十個位元組
壞處:
- 存在無法被正确複制的SQL,比如擷取目前時間戳、使用CURRENT_USER()函數的語句
- 更新必須串行,這需要更多的鎖
基于行的複制
MySQL5.1開始支援基于行的複制,這種方式會将實際資料記錄在二進制日志中
好處:
- 可以正确複制每一行,對于一些需要從大表查詢結果彙總到小表的更新,如果更新行數很少,效率相對于基于語句的複制更高效
壞處:
- 對于更新行數很大的更新,會使二進制日志事件非常龐大,給主庫記錄日志和備庫複制增加額外的負載
複制拓撲結構
可以在任意主庫和備庫之間建立複制,唯一的限制是每個備庫隻能有一個主庫,這樣一來,複制拓撲結構就非常多了,不同的拓撲結構隻須遵循以下原則:
- 一個備庫隻能有一個主庫
- 每個備庫必須有一個唯一的伺服器ID
- 一個主庫可以有多個備庫
- 一個備庫可以把其主庫上的資料變化傳遞到其他備庫,需要log_slave_updates選項設定為1,即允許備庫将其重放的事件也記錄到自身的二進制日志中
複制拓撲結構很多,下面介紹幾種常見的
一主多備
最簡單的拓撲結構,再有少量寫大量讀的時候,可以通過讀寫分離減小負載。還有,可以将備庫放到不同地理位置的機房,做資料備份容災
主動-主動模式下的主-主複制
主-主複制(也叫雙主複制或雙向複制),每一個都被配置成對方的主庫和備庫。該拓撲可能的應用場景是兩個處于不同地理位置的辦公室,并且都需要可寫的資料拷貝。這種配置最大的問題是如何解決沖突,兩個可寫的互主伺服器導緻的問題非常多,通常發生在兩天伺服器同時修改同一行記錄,或者同時向包含auto_increment列的表裡插入資料,會造成兩邊資料不一緻
主動-被動模式下的主-主複制
和上一種主要差別在于其中一台伺服器是隻讀的被動伺服器。這種方式使得切換主動和被動伺服器非常友善,因為伺服器配置是對稱的。這使得故障轉移和故障恢複很容易。它也可以讓你在不關閉伺服器的情況下維護、優化表。
級聯複制
直接從屬主庫的備庫太多時,連接配接到主庫的I/O線程比較多,增大主庫壓力,它的缺點是中間層出現錯誤,會影響到多個伺服器,中間層層次越多,故障處理越複雜
參考
[1] 《高性能MySQL》