一、什麼叫mysql複製?
關於mysql複製,我是這樣理解的:將某一臺主機上的Mysql數據複製到其它主機(slaves)上,並重新執行一遍從而實現當前主機上的mysql數據與(master)主機上數據保持一致的過程我們可以稱爲複製。
複製過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日誌文件,並維護文件的一個索引以跟蹤日誌循環。這些日誌可以記錄發送到從服務器的更新。當一個從服務器連接主服務器時,它通知主服務器從服務器在日誌中讀取的最後一次成功更新的位置。從服務器接收從那時起發生的任何更新,然後封鎖並等待主服務器通知新的更新。
二、mysql複製是如何工作的?
從上圖看mysql的主從複製整體來說分爲3個部分:
1、master將狀態信息的改變記錄到二進制日誌(binary log)中(這些記錄叫做二進制日誌事件,binary log events);
2、slave將master的binary log events拷貝到它的中繼日誌(relay log);
3、slave重做中繼日誌中的事件,將狀態信息的改變存儲到本地磁盤行成數據;
詳細描述如下:
首先該過程的第一部分就是master記錄二進制日誌。在每個事務更新數據完成之前,master在二日誌記錄這些改變。MySQL將事務串行的寫入二進制日誌,即使事務中的語句都是交叉執行的。在事件寫入二進制日誌完成後,master通知存儲引擎提交事務。
接下來就是slave將master的binary log拷貝到它自己的中繼日誌。先是slave開始一個工作線程——I/O線程,I/O線程在master上打開一個普通的連接,然後開始binlog dump process從master的二進制日誌中讀取事件,如果已經跟上master,它會睡眠並等待master產生新的事件(Seconds_Behind_Masterk可以觀察落後的狀態),I/O線程將這些事件寫入中繼日誌。
最後SQL thread(SQL從線程)從中繼日誌讀取事件,並執行事件語句更新slave的數據,使其與master中的數據一致。
此外,在master中也有一個工作線程:和其它MySQL的連接一樣,slave在master中打開一個連接也會使得master開始一個線程。複製過程有一個很重要的限制——複製在slave上是串行化的,也就是說master上的並行更新操作不能在slave上並行操作(slave會有數據上的延時)。
三、複製能解決的問題及mysql支持的複製類型:
1、MySQL複製技術有以下一些好處:
1.1、數據分佈 (Data distribution )
1.2、可以實現負載均衡(load balancing),通常所說的讀寫分離
1.3、可以實現數據的備份(Backups),但是不能當真正意義上數據備份來用
1.4、高可用性和容錯行(比如雙主模型中的互爲主從能實現高可用)
2、複製類型:
2.1、基於語句的複製(statement):在主服務器上執行的SQL語句,在從服務器上執行同樣的語句。
優點:基於語句的複製,效率比較高;需要注意地方:可能無法精確複製,比如sql中更新時間的時候如果不是精準值而是time();什麼的,由於主從複製有延時導致數據的不一致。
2.2、基於行的複製(row):把改變的內容複製過去,而不是把命令在從服務器上執行一遍。數據複製相對安全,但是產生的日誌文件會過大,比如update某一範圍來數據的狀態,這個範圍有1W條數據,就會產生1W條update語句;
2.3、混合類型的複製(mixed): mysql5.5默認採用混合類型的複製,也就是上面的兩種根據情況變換着複製。此方法可能會打亂日誌的結構,一會基於語句一會兒基於行,日誌排查日誌的可能看起來不太好使;
3、mysql複製中需要注意的問題:
3.1、主從服務器mysql的版本,主庫的版本可以低於從庫,但是從庫的版本一定不能低於主庫(從版本 >= 主版本)
3.2、爲了複製的安全額外設置:
從服務器:
read_only=ON 關閉寫
skip-slave-start=ON 關閉從服務自動啓動
主服務器:
sync_binlog=ON 同步事務的二進制日誌
四、主從複製的配置:
1、主從服務器各自需要的準備操作
1.1、主服務器:
a、創建具有複製權限的用戶帳號;
mysql> grant replication slave, replication client on *.* to copyuser@'172.16.5.%' identified by '123456';
mysql> flush privileges;
b、設置server-id;
# server-id = 10
c、啓用二進制日誌;
# log-bin = /mydata/log/mysql-bin 日誌存放位置
# binlog_format = row 基於行復制
1.2、從服務器:
a、啓用中繼日誌;(可選:關閉二進制日誌)
# relay-log = /mydata/log/relay-bin 日誌存放位置
# read-only = 1 設置爲只讀(對root權限賬號無效)
b、設置server-id;
# server-id = 20
c、啓動複製線程;
# change master to master_host='172.16.5.100' master_user='copyuser' master_password='123456'
# slave start;
查看狀態:
# show slave status\G;
# show processlist;
在這裏主要是看:
Slave_IO_Running = Yes
Slave_SQL_Running = Yes
如果需要只複製某些庫可以指定過濾條件;
replicate-do-db = db1,db2 只複製某庫
replicate-do-table = db1.mytbl 只複製某庫某表
replicate_ignore_db = db3 不復制某庫
replicate_ignore_table = db1.nytb3 不復制某庫中的某表
五、深入瞭解複製
1、一主多從
由一個master和一個slave組成複製系統是最簡單的情況。Slave之間並不相互通信,只能與master進行通信。在實際應用場景中,MySQL複製90%以上都是一個Master複製到一個或者多個Slave的架構模式,主要用於讀壓力比較大的應用的數據庫端廉價擴展解決方案。
在上圖中,如果一主拖了多個從的話,這時主庫既要負責寫又要負責爲幾個從庫提供二進制日誌,此時可以稍做調整,將二進制日誌只給某一從,這一從再開啓二進制日誌並將自己的二進制日誌再發給其它從,或者是乾脆這個從不記錄只負責將二進制日誌轉發給其它從,這樣架構起來性能可能要好得多,而且數據之間的延時應該也稍微要好一些。
2、主主複製
上圖中,Master-Master複製的兩臺服務器,既是master,又是另一臺服務器的slave。這樣,任何一方所做的變更,都會通過複製應用到另外一方的數據庫中。在這種複製架構中,各自上運行的不是同一db,比如左邊的是db1,右邊的是db2,db1的從在右邊反之db2的從在左邊,兩者互爲主從,再輔助一些監控的服務還可以實現一定程度上的高可以用。
3、主動-被動模式(HA)
上圖中,這是由master-master結構變化而來的,它避免了M-M的缺點,實際上,這是一種具有容錯和高可用性的系統。它的不同點在於其中只有一個節點在提供讀寫服務,另外一個節點時刻準備着,當主節點一旦故障馬上接替服務。比如通過corosync+pacemaker+drbd+mysql就可以提供這樣一組高可用服務,主備模式下再跟着slave服務器,也可以實現讀寫分離。
4、mysql-5.5支持半同步複製
mysql複製我們都知道是基於異步來實現的,但是從mysql-5.5開始,支持半自動複製。在以前版本中異步(asynchronous)複製中,主庫在執行完一些事務後,是不會管備庫的進度的。如果備庫處於落後,而更不幸的是主庫此時又出現Crash(例如宕機),這時備庫中的數據就是不完整的。簡而言之,在主庫發生故障的時候,我們無法使用備庫來繼續提供數據一致的服務了。Semisynchronous Replication(半同步複製)則一定程度上保證提交的事務已經傳給了至少一個備庫。Semi synchronous中,僅僅保證事務的已經傳遞到備庫上,但是並不確保已經在備庫上執行完成了。
此外,還有一種情況會導致主備數據不一致。在某個session中,主庫上提交一個事務後,會等待事務傳遞給至少一個備庫,如果在這個等待過程中主庫Crash,那麼也可能備庫和主庫不一致,這是很致命的。如果主備網絡故障或者備庫掛了,主庫在事務提交後等待10秒(rpl_semi_sync_master_timeout的默認值)後,就會繼續。這時,主庫就會變回原來的異步狀態。
MySQL在加載並開啓Semi-sync插件後,每一個事務需等待備庫接收日誌後才返回給客戶端。如果做的是小事務,兩臺主機的延遲又較小,則Semi-sync可以實現在性能很小損失的情況下的零數據丟失。