先來看下MYSQL異步復(fù)制的概念:
異步復(fù)制:MySQL本身支持單向的、異步的復(fù)制。異步復(fù)制意味著在把數(shù)據(jù)從一臺機器拷貝到另一臺機器時有一個延時 – 最重要的是這意味著當應(yīng)用系統(tǒng)的事務(wù)提交已經(jīng)確認時數(shù)據(jù)并不能在同一時刻拷貝/應(yīng)用到從機。通常這個延時是由網(wǎng)絡(luò)帶寬、資源可用性和系統(tǒng)負載決定的。然而,使用正確的組件并且調(diào)優(yōu),復(fù)制能做到接近瞬時完成。
當主庫有更新的時候,主庫會把更新操作的SQL寫入二進制日志(Bin log),并維護一個二進制日志文件的索引,以便于日志文件輪回(Rotate)。在從庫啟動異步復(fù)制的時候,從庫會開啟兩個I/O線程,其中一個線程連接主庫,要求主庫把二進制日志的變化部分傳給從庫,并把傳回的日志寫入本地磁盤。另一個線程則負責讀取本地寫入的二進制日志,并在本地執(zhí)行,以反映出這種變化。較老的版本在復(fù)制的時候只啟用一個I/O線程,實現(xiàn)這兩部分的功能。
同步復(fù)制:同步復(fù)制可以定義為數(shù)據(jù)在同一時刻被提交到一臺或多臺機器,通常這是通過眾所周知的“兩階段提交”做到的。雖然這確實給你在多系統(tǒng)中保持一致性,但也由于增加了額外的消息交換而造成性能下降。
使用MyISAM或者InnoDB存儲引擎的MySQL本身并不支持同步復(fù)制,然而有些技術(shù),例如分布式復(fù)制塊設(shè)備(簡稱DRBD),可以在下層的文件系統(tǒng)提供同步復(fù)制,允許第二個MySQL服務(wù)器在主服務(wù)器丟失的情況下接管(使用第二服務(wù)器的復(fù)本)。要了解更多信息,
MYSQL 5。5開始,支持半自動復(fù)制。之前版本的MySQL Replication都是異步(asynchronous)的,主庫在執(zhí)行完一些事務(wù)后,是不會管備庫的進度的。如果備庫不幸落后,而更不幸的是主庫此時又出現(xiàn)Crash(例如宕機),這時備庫中的數(shù)據(jù)就是不完整的。簡而言之,在主庫發(fā)生故障的時候,我們無法使用備庫來繼續(xù)提供數(shù)據(jù)一致的服務(wù)了。
Semisynchronous Replication則一定程度上保證提交的事務(wù)已經(jīng)傳給了至少一個備庫。
Semi synchronous中,僅僅保證事務(wù)的已經(jīng)傳遞到備庫上,但是并不確保已經(jīng)在備庫上執(zhí)行完成了。
此外,還有一種情況會導致主備數(shù)據(jù)不一致。在某個session中,主庫上提交一個事務(wù)后,會等待事務(wù)傳遞給至少一個備庫,如果在這個等待過程中主庫Crash,那么也可能備庫和主庫不一致,這是很致命的。(在主庫恢復(fù)后,可以通過參數(shù)Rpl_semi_sync_master_no_tx觀察)
如果主備網(wǎng)絡(luò)故障或者備庫掛了,主庫在事務(wù)提交后等待10秒(rpl_semi_sync_master_timeout的默認值)后,就會繼續(xù)。這時,主庫就會變回原來的異步狀態(tài)。
MySQL在加載并開啟Semi-sync插件后,每一個事務(wù)需等待備庫接收日志后才返回給客戶端。如果做的是小事務(wù),兩臺主機的延遲又較小,則Semi-sync可以實現(xiàn)在性能很小損失的情況下的零數(shù)據(jù)丟失。
主機Crash時的處理
備庫Crash時,主庫會在某次等待超時后,關(guān)閉Semi-sync的特性,降級為普通的異步復(fù)制,這種情況比較簡單。
主庫Crash后,那么可能存在一些事務(wù)已經(jīng)在主庫Commit,但是還沒有傳給任何備庫,我們姑且稱這類事務(wù)為"墻頭事務(wù)"。"墻頭事務(wù)"都是沒有返回給客戶端的,所以發(fā)起事務(wù)的客戶端并不知道這個事務(wù)是否已經(jīng)完成。
這時,如果客戶端不做切換,只是等Crash的主庫恢復(fù)后,繼續(xù)在主庫進行操作,客戶端會發(fā)現(xiàn)前面的"墻頭事務(wù)"都已經(jīng)完成,可以繼續(xù)進行后續(xù)的業(yè)務(wù)處理;另一種情況,如果客戶端Failover到備庫上,客戶端會發(fā)現(xiàn)前面的“墻頭事務(wù)”都沒有成功,則需要重新做這些事務(wù),然后繼續(xù)進行后續(xù)的業(yè)務(wù)處理。
可以做多個備庫,任何一個備庫接收完成日志后,主庫就可以返回給客戶端了。
網(wǎng)絡(luò)傳輸在并發(fā)線程較多時,一次可能傳輸很多日志,事務(wù)的平均延遲會降低。
"墻頭事務(wù)"在墻頭上的時候,是可以被讀取的,但是這些事務(wù)在上面Failover的場景下,是被認為沒有完成的。
默認情況下MySQL的復(fù)制是異步的,Master上所有的更新操作寫入Binlog之后并不確保所有的更新都被復(fù)制到Slave之上。異步操作雖然效率高,但是在Master/Slave出現(xiàn)問題的時候,存在很高數(shù)據(jù)不同步的風險,甚至可能丟失數(shù)據(jù)。
MySQL5.5引入半同步復(fù)制功能的目的是為了保證在master出問題的時候,至少有一臺Slave的數(shù)據(jù)是完整的。在超時的情況下也可以臨時轉(zhuǎn)入異步復(fù)制,保障業(yè)務(wù)的正常使用,直到一臺salve追趕上之后,繼續(xù)切換到半同步模式。
Master:
INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so’;
SET GLOBAL rpl_semi_sync_master_enabled=1;
SET GLOBAL rpl_semi_sync_master_timeout=1000; (1s, default 10s)
Slave:
INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave.so’;
SET GLOBAL rpl_semi_sync_slave_enabled=1;
復(fù)制心跳(用戶檢測復(fù)制是否中斷)
MySQL5.5提供的新的配置master_heartbeat_period,能夠在復(fù)制停止工作和出現(xiàn)網(wǎng)絡(luò)中斷的時候幫助我們迅速發(fā)現(xiàn)問題。
啟用方法:
STOP SLAVE;
CHANGE MASTER TO master_heartbeat_period= milliseconds;
START SLAVE;
Slave自動恢復(fù)同步
在MySQL5.5版本之前,MySQL Slave實例在異常終止服務(wù)之后,可能導致復(fù)制中斷,并且relay binlog可能損壞,在MySQL再次啟動之后并不能正常恢復(fù)復(fù)制。在MySQL5.5中這一問題得到了解決,MySQL可以自行丟棄順壞的而未處理的數(shù)據(jù),重新從master上獲取源數(shù)據(jù),進而回復(fù)復(fù)制。
跳過指定復(fù)制事件
在多Master或環(huán)形復(fù)制的情況下,處于復(fù)制鏈條中間的服務(wù)器異常,可以通過
CHANGE MASTER TO MASTER_HOST=xxx IGNORE_SERVER_IDS=y
跳過出問題的MySQL實例。
自動轉(zhuǎn)換字段類型
MySQL5.1在基于語句的復(fù)制下,支持部分的字段轉(zhuǎn)換,但是行級的會報錯。MySQL5.5語句和行級復(fù)制都已支持。還可以通過 SLAVE_TYPE_CONVERSIONS 控制轉(zhuǎn)換的方向。