java編程——MySQL增強(Loss-less)半同步複製

許多用戶在他們的數據庫環境中使用半同步複製架構以提高數據的完整性。今天我要向大家介紹一下MySQL在5.7版本中針對半同步複製增加的新特性,這個新特性進一步增強了主庫和備庫之間的數據完整性。

在存儲引擎層提交之前等待從庫ACK

正如你所知的,在半同步複製架構中,主庫上的事務提交之前會等待一個從庫返回ACK信號。為了進一步增加數據的完整性,新的特性將等待從庫返回ACK信號的時間點提前了(相對於MySQL5.5以及MySQL5.6),新特性中主庫上的事務會在存儲引擎層提交之前一直等待從庫返回ACK信號。

java編程——MySQL增強(Loss-less)半同步複製

有了這個新特性之後,半同步複製可以保證:

  • 在主庫crash的情況下,所有在主庫上已經提交的事務已經被複制到至少一個從庫上

顯而易見,因為主庫上的事務無法提交,除非從庫返回了ACK信號(或者超時)。

這對於用戶來說有兩個有利點:

  • 強數據完整性,並解決了幻讀的問題
  • 簡化主庫Crash Recovery的過程

強數據完整性解決幻讀問題

在MySQL 5.5以及MySQL 5.6開啟半同步複製的場景下,主庫上的事務在存儲引擎層提交之後,需要等待從庫返回ACK信號。並且在接收到從庫返回ACK信號或者等待超時才會返回給客戶端一個提交結果。

java編程——MySQL增強(Loss-less)半同步複製

存儲引擎層的提交,會持久化記錄並且釋放這些記錄上的鎖。所以在存儲引擎層提交之後,其餘的會話可以操作並讀取這些記錄,即使這個會話還在等待從庫返回ACK信號。這樣在主庫crash,從庫接管主庫的情況下,產生幻讀的現象。

java編程——MySQL增強(Loss-less)半同步複製

在這個新特性中,不會發生幻讀。User2在第一次SELECT的時候不會獲取3這個值,因為3這條記錄還沒有複製從庫,所以並沒有在存儲引擎層提交。

簡化主庫Crash Recovery的過程

在MySQL 5.7.2之前的版本中,用戶在恢復crash掉的主庫的時候,需要做以下操作:

  • 手動清除並沒有被複制到從庫上的binlog事務
  • 手動回滾已經提交但是還沒有被複制的事務

因為新的特性保證所有的事務在提交之前都至少複製到一個從庫上了,所以第二步可以不用做了。

如何設置新特性

這個特性的設置很簡單,用戶無需任何設置,因為在MySQL 5.7.2版本之後該特性是默認開啟的。用戶可以設置 rpl_semi_sync_master_wait_point 變量控制主庫等待從庫返回ACK信號的時間點。

這是一個全局、可動態修改的參數。在5.7.2版本之後,該變量的默認值是 AFTER_SYNC ,該值表示,主庫上的事務會在flush binlog之後,在存儲引擎層提交之前的時間點,等待從庫返回ACK信號。

你也可以將該參數設置為 AFTER_COMMIT 值不開啟新特性,保持和之前版本一樣的機制。但是我想不到一個理由讓用戶設置該變量為 AFTER_COMMIT 值。開啟新特性並沒有副作用,也不會對數據庫性能產生影響。

Dump線程的優化

在開發這個特性的過程中,我們對Dump線程做了一些優化。我們重構了Dump線程先關的代碼,但是更重要的是,在Dump線程讀取binlog event的時候,Dump線程不會再去獲取binlog鎖。這一改進增加了主庫的一個吞吐量並且減小了主從之間的延遲。

最後

總而言之,這個新特性保證了主庫和從庫之間的數據完整性、一致性,並不會帶來任何副作用以及性能印象。我強烈推薦你去嘗試該特性。

A special thanks to Mr. Zhenxing Zhou a community user who contributed a patch implementi

java編程——MySQL增強(Loss-less)半同步複製


分享到:


相關文章: