1. 程式人生 > > 【可靠性】Mysql 5.7 降低了半同步復制-數據丟失的風險

【可靠性】Mysql 5.7 降低了半同步復制-數據丟失的風險

time 原理 cat jpg 出現 nsa read pos ngs

如果你的生產線開啟了半同步復制,那麽對數據的一致性會要求較高,但在MySQL5.5/5.6裏,會存在數據不一致的風險。有這麽一個場景,客戶端提交了一個事務,master把binlog發送給slave,在發送的期間,網絡出現波動,此時Binlog Dump線程發送就會卡住,要等待slave把binlog寫到本地的relay-log裏,然後給master一個反饋,等待的時間以rpl_semi_sync_master_timeout參數為準,默認為10秒。在這等待的10秒鐘裏,在其他會話裏,查看剛才的事務是可以看見的,此時一旦master發生宕機,由於binlog沒有發送給slave,前端app切到slave查看,就會發現剛才已提交的事務不見了。

例如,在雙十一期間,搶購產品,出現了上面這種情況,用戶下了一個訂單,由於網絡波動,發送binlog給slave卡住了(10秒),那個用戶又刷新了一下瀏覽器,看見了剛才下的訂單,此時master宕機,通過高可用failover到了slave上(slave未接收到那個binlog),他發現我剛才下的訂單沒了,他肯定大罵,老子錢花了,訂單不見了,直接投訴。

為了解決這種問題,MySQL5.7 改善了半同步復制這個缺陷。通過rpl_semi_sync_master_wait_point這個參數加以控制,默認是AFTER_SYNC,官方推薦用這個,它的工作原理是:master把binlog發送給slave,只有在slave把binlog寫到本地的relay-log裏,才提交到存儲引擎層,然後把請求返回給客戶端,客戶端才可以看見剛才提交的事務。如果slave未保存到本地的relay-log裏,客戶端是看不見剛才的事務的,這樣就不會造成上述那個場景發生。另一個值是AFTER_COMMIT,這個值是采用老式的MySQL5.5/5.6半同步復制工作。

另外:在MySQL5.7 半同步復制可以通過rpl_semi_sync_master_wait_slave_count參數指定有幾臺slave接收到了binlog才成功返回客戶端請求,默認是一臺,但不能指定是具體哪臺。

參考:

技術分享圖片

AFTER_SYNC (the default): The master writes each transaction to its binary log and the slave, and syncs the binary log to disk. The master waits for slave acknowledgment of transaction receipt after the sync. Upon receiving acknowledgment, the master commits the transaction to the storage engine and returns a result to the client, which then can proceed.
主庫把每一個事務寫到二進制日誌並保存磁盤上,且發送給從庫。主庫在等待從庫寫到自己的relay-log裏確認信息。在接到確認信息後,主數據庫把事務寫到存儲引擎裏並把相應結果反饋給客戶端,客戶端將在那時進行處理。

AFTER_COMMIT: The master writes each transaction to its binary log and the slave, syncs the binary log, and commits the transaction to the storage engine. The master waits for slave acknowledgment of transaction receipt after the commit. Upon receiving acknowledgment, the master returns a result to the client, which then can proceed.
主庫把每一個事務寫到二進制日誌並保存磁盤上,且發送給從庫,並把事務寫到存儲引擎裏。主庫在等待從庫寫到自己的relay-log裏確認信息。在接到確認信息後,主庫把相應結果反饋給客戶端,客戶端將在那時進行處理。

The replication characteristics of these settings differ as follows:
這兩個參數不同之處在於:

With AFTER_SYNC, all clients see the committed transaction at the same time: After it has been acknowledged by the slave and committed to the storage engine on the master.。Thus, all clients see the same data on the master.
在設置為AFTER_SYNC參數,所有的客戶端可以同時看到提交的數據:在得到從庫寫到自己的relay-log裏的確認信息後,並把事務寫到存儲引擎裏。這樣,所有的客戶端都可以在主庫上看到同樣的數據。

In the event of master failure, all transactions committed on the master have been replicated to the slave (saved to its relay log). A crash of the master and failover to the slave is lossless because the slave is up to date.
主庫報錯,所有已經寫到從庫的事務都已經保存到了relay log裏。主庫的崩潰,HA切換到從庫,不會帶來任何損失,因為從庫的relay-log的數據是最新的。

With AFTER_COMMIT, the client issuing the transaction gets a return status only after the server commits to the storage engine and receives slave acknowledgment. After the commit and before slave acknowledgment, other clients can see the committed transaction before the committing client.
在設置為AFTER_COMMIT 參數,發起事務的客戶端僅在服務器向存儲引擎寫入數據並接受從庫得到確認之後才返回狀態。在寫入數據後和得到從庫確認之前,其他的客戶端可以看到在這一事務。

If something goes wrong such that the slave does not process the transaction, then in the event of a master crash and failover to the slave, it is possible that such clients will see a loss of data relative to what they saw on the master.
如果出現了某種錯誤,比如說從庫的sql_thread線程沒有執行,那麽主庫崩潰和故障轉移給從服務器的前提下,有可能這個客戶端會丟失那些他們曾經在主庫上看到的信息。

【可靠性】Mysql 5.7 降低了半同步復制-數據丟失的風險