MySQL 5.7 半同步復制增強【轉】


MySQL默認的復制都是異步的,在服務器崩潰時丟失事務是使用異步復制不可避免的結果。而5.5之后推出的一項新功能:半同步復制,可以限制事務丟失的數量。

MySQL5.7在5.6/5.5的基礎上增強了幾點功能:

1)無數據丟失

MySQL5.6/5.5半同步復制的原理:提交事務的線程會被鎖定,直到至少一個Slave收到這個事務,由於事務在被提交到存儲引擎之后才被發送到Slave上,所以事務的丟失數量可以下降到最多每線程一個。因為事務是在被提交之后才發送給Slave的,當Slave沒有接收成功,並且Master掛了,會導致主從不一致:主有數據,從沒有數據。如下面的情況:(AFTER_COMMIT)

復制代碼
客戶端執行一個事務,master接收到之后提交后並把事務發送給slave,在發送的期間網絡出現波動,但要等待slave把binlog寫到本地的relay-log,然后給master一個返回信息,等待以rpl_semi_sync_master_timeout參數設置的超時為准(默認為10秒)響應。在這等待的10秒里,其他會話查可以看到Master上的事務,此時一旦master發生宕機,由於事務沒有發送給slave,而master已經提交了,導致數據不一致。
例子:
A客戶端執行的事務將字段Z從0修改為1。
1.A提交事務到master
2.master寫binlog
3.master commit事務到存儲引擎,再把事務發送給slave
4.master commit成功了!
說明:此時還未收到slave確認,A還在等待slave的響應,但是另外客戶端B已經可以看到字段Z為1了。假如此時master崩潰,如果slave實際收到剛才的事務僅僅是master未收到確認,那么此時slave的數據還是正確的也是Z=1,客戶端切換到slave后,都看到Z=1,但是如果slave沒有實際收到剛才的事務,那么此時slave上的z=0,導致主從數據不一直。
復制代碼

MySQL5.7在Master事務提交的時間方面做了改進(rpl_semi_sync_master_wait_point:AFTER_COMMIT\AFTER_SYNC),事務是在提交之前發送給Slave(默認,after_sync),當Slave沒有接收成功,並且Master宕機了,不會導致主從不一致,因為此時主還沒有提交,所以主從都沒有數據。MySQL5.7也支持和MySQL5.5\5.6一樣的機制:事務提交之后再發給Slave(after_commit)如下面的情況:(AFTER_SYNC)

復制代碼
客戶端執行一個事務,master接收到之后就把事務發送給slave,slave收到事務之后,然后給master一個返回信息,master再提交事務。在slave返回信息的時間里(以rpl_semi_sync_master_timeout參數為准,默認為10秒),其他會話查看不到Master上的最新事務,因為master都還沒提交事務,此時一旦master發生宕機,由於事務沒有發送給slave,並且master也沒有提交數據,主從數據都沒有更改,所以不會出現數據不一致。
例子:
A客戶端執行的事務講字段Z從0修改為1。
1.A提交事務到master 2.master寫binlog
3.master發送事務給slave,不提交! 4.master等待slave確認 此時z=0,沒有任何客戶端能看到z=1的結果,因為master還沒提交。 5.master收到slave確認,master開始commit到存儲引擎 6.master commit成功了!master返回結果給客戶端 說明:假如第4步時master崩潰,客戶端切換到slave,如果slave接收到事務,並響應master,那么此時主從的z=1,如果slave未接收到事務和響應,那么此時z=0,無論哪種狀態,對於所有客戶端數據庫都是一致,事務都沒有丟失。
復制代碼

參數rpl_semi_sync_master_wait_point該參數控制半同步復制在哪個點(提交后再等待響應還是響應后再提交)等待slave的響應,默認AFTER_SYNC(slave響應后再提交),可選值有AFTER_COMMIT(提交后再等待響應)。

after_commit:master把每一個事務寫到二進制日志並保存到磁盤上,並且提交(commit)事務,再把事務發送給從庫,開始等待slave的應答。響應后master返回結果給客戶端,客戶端才可繼續。

after_sync  :master把每一個事務寫到二進制日志並保存磁盤上,並且把事務發送給從庫,開始等待slave的應答。確認slave響應后,再提交(commit)事務到存儲引擎,並返回結果給客戶端,客戶端才可繼續。

總之,MySQL5.7是在Master收到Slave應答之后才Commit事務,MySQL5.6/5.5是在Master Commit之后才等待Slave的應答。MySQL5.7半同步的好處就是在確認事務復制到Slave之前,並發的其他線程看不到當前事務的數據。當Master故障時,要么提交的事務已經復制到Slave,要么全部都沒提交,這樣就保證了數據的一致性,推薦閱讀MySQL 5.7 深度解析: 半同步復制技術。 

2)更快的半同步復制。

MySQL5.5/5.6的半同步復制是一個單工通訊方式,master把事務發送完畢后,要接收和處理slave的應答,處理完應答之后才能繼續發送下一個事務,示意圖如下:

MySQL5.7的半同步復制創建了單獨的應答接收線程,變成了雙工模式,發送和接收互不影響。因為有了相應的線程處理,發送效率得到大幅提升,相比MySQL5.5/5.6延遲會小很多,性能得到大幅提升。示意圖如下:

注意:MySQL5.7單獨的應答接收線程在開啟半同步復制的時候默認就創建了,不需要額外的設置。

3)等待多個Slave應答。

在半同步復制中,Master發送事務默認至少有一個Slave得到響應才能繼續下一個事務。MySQL5.7之后用戶可以設置應答的Slave數量,並且可以通過參數rpl_semi_sync_master_wait_for_slave_count:該變量控制slave應答的數量,默認是1,表示master接收到幾個slave應答后才commit。在多從的環境下,設置大於1可以提高數據的可靠性。

4)半同步復制的建立監控

 如何建立半同步復制:可以看官方文檔或則之前寫的初識 MySQL 5.5、5.6 半同步復制

復制代碼
主上執行:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.07 sec)

mysql> SET GLOBAL rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)
為了保證重啟后繼續生效,需要在配置文件里加入:rpl_semi_sync_master_enabled = 1

從上執行:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.04 sec)

mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
為了保證重啟后繼續生效,需要在配置文件里加入:rpl_semi_sync_slave_enabled = 1

開啟復制:設置好半同步復制的插件和開啟半同步功能之后,復制模式就默認用半同步了
mysql> CHANGE MASTER TO MASTER_HOST='10.0.3.141',MASTER_USER='repl',MASTER_PASSWORD='Repl_123456',MASTER_LOG_FILE='mysql-bin-3306.000001',MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.30 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

開啟成功后,slave的error log里會出現:半同步復制是跟 IO_THREAD 有直接關系,跟 SQL_THREAD 沒關系。也就是說SLAVE 從庫接收完二進制日志后給 master 主庫一個確認,並不管relay-log中繼日志是否正確執行完。即使SQL線程報錯了,半同步復制還是不會切換成異步復制
[Note] Slave I/O thread: Start semi-sync replication to master 'repl@10.0.3.141:3306' in log 'mysql-bin-3306.000001' at position 154
復制代碼

如何監控半同步復制:可以看官方文檔或則之前寫的初識 MySQL 5.5、5.6 半同步復制

復制代碼
主上:
mysql> show variables like 'rpl_semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+ 
6 rows in set (0.00 sec)

mysql> show global status like 'rpl_semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

從上:
mysql> show variables like 'rpl_semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

mysql> show global status like 'rpl_semi%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)
復制代碼

半同步成功開啟之后,在主上show processlist可以看到:

Waiting for semi-sync ACK from slave;

針對上面的參數和變量說明:

復制代碼
主上:
rpl_semi_sync_master_enabled:表示主上是否開啟半同步復制功能,可以動態修改。可選值:ON\OFF rpl_semi_sync_master_timeout:為了防止半同步復制中主在沒有收到S發出的確認發生堵塞,用來設置超時,超過這個時間值沒有收到信息,則切換到異步復制,執行操作。默認為10000毫秒,等於10秒,這個參數動態可調,表示主庫在某次事務中,如果等待時間超過10秒,那么則降級為異步復制模式,不再等待SLAVE從庫。如果主庫再次探測到,SLAVE從庫恢復了,則會自動再次回到半同步復制模式。可以設置成1000,即1秒。
rpl_semi_sync_master_wait_for_slave_count控制slave應答的數量,默認是1,表示master接收到幾個slave應答后才commit。
rpl_semi_sync_master_wait_no_slave :當一個事務被提交,但是Master沒有Slave連接,這時M不可能收到任何確認信息,但M會在時間限制范圍內繼續等待。如果沒有Slave鏈接,會切換到異步復制。是否允許master每個事務提交后都要等待slave的接收確認信號。默認為on,每一個事務都會等待。如果為off,則slave追趕上后,也不會開啟半同步復制模式,需要手工開啟。
rpl_semi_sync_master_wait_point該參數表示半同步復制的主在哪個點等待從的響應,默認AFTER_SYNC在得到slave的應答后再commit,可選值AFTER_COMMIT。

從上:
rpl_semi_sync_slave_enabled:表示從上是否開啟半同步復制功能,可以動態修改。可選值:ON\OFF
復制代碼
復制代碼
Rpl_semi_sync_master_clients :說明支持和注冊半同步復制的已連Slave數。
Rpl_semi_sync_master_net_avg_wait_time :master等待slave回復的平均等待時間,單位毫秒。
Rpl_semi_sync_master_net_wait_time :master總的等待時間。
Rpl_semi_sync_master_net_waits :master等待slave回復的的總的等待次數,即半同步復制的總次數,不管失敗還是成功,不算半同步失敗后的異步復制。
Rpl_semi_sync_master_no_times :master關閉半同步復制的次數。 
Rpl_semi_sync_master_no_tx :master沒有收到slave的回復而提交的次數,可以理解為master等待超時的次數,即半同步模式不成功提交數量。
Rpl_semi_sync_master_status :ON是活動狀態(半同步),OFF是非活動狀態(異步),用於表示主服務器使用的是異步復制模式,還是半同步復制模式。
Rpl_semi_sync_slave_status :Slave上的半同步復制狀態,ON表示已經被啟用,OFF表示非活動狀態。
Rpl_semi_sync_master_tx_avg_wait_time :master花在每個事務上的平均等待時間。 
Rpl_semi_sync_master_tx_wait_time :master總的等待時間。
Rpl_semi_sync_master_tx_waits :master等待成功的次數,即master沒有等待超時的次數,也就是成功提交的次數
Rpl_semi_sync_master_wait_pos_backtraverse :master提交后來的先到了,而先來的還沒有到的次數。
Rpl_semi_sync_master_wait_sessions :前有多少個session因為slave的回復而造成等待。
Rpl_semi_sync_master_yes_tx :master成功接收到slave的回復的次數,即半同步模式成功提交數量。  
復制代碼

總之,關於半同步復制的測試說明可以看初識 MySQL 5.5、5.6 半同步復制這篇文章。半同步復制的好處:半同步復制可以有效的限制事務丟失的數量,更好的保證數據的安全和一致性;半同步復制的壞處:更新、插入、刪除的速度要比異步復制要慢,因為多了一個"從返回信息給主"的步驟。要是出現異常:網絡問題或則數據庫問題,半同步復制和異步復制就會來回切換,導致主庫的更新、插入、刪除操作會受到影響。

...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM