rpl_semi_sync_master_wait_no_slave 參數研究實驗


最近在研究MySQL,剛學到半同步。

半同步的配置中,關於這兩個參數:

  rpl_semi_sync_master_wait_no_slave

  rpl_semi_sync_master_wait_for_slave_count

發現很不好搞懂,請教了一些老師,也做了一些資料搜索,每個人給我的答案都不同:

  

中文網絡上一些典型的說法,這些都是錯誤的!!!
rpl_semi_sync_master_wait_for_slave_count:
  控制slave應答的數量,默認是1,表示master接收到幾個slave應答后才commit。
   rpl_semi_sync_master_wait_no_slave :
  1.需要等待幾個slave節點的ACK,否則一直waiting。
  2.當一個事務被提交,但是Master沒有Slave連接,這時M不可能收到任何確認信息,但M會在時間限制范圍內繼續等待。如果沒有Slave鏈接,會切換到異步復制。是否允許master每個事務提交后都要等待slave的接收確認信號。默認為on,每一個事務都會等待。如果為off,則slave追趕上后,也不會開啟半同步復制模式,需要手工開啟。

 

好奇心驅使我通過實驗來驗證大家的說法,可惜的是——都是錯的。通過官方文檔,看的雲里霧里的,只好自己探索。

 

探索內容

  半同步參數

  • rpl_semi_sync_master_wait_no_slave(重點)
  • rpl_semi_sync_master_wait_for_slave_count

環境信息

role

ip

port

hostname

etc

master

192.168.188.101

4306

mysqlvm1

提示符為mysql>

 

 

 

 

 

slave

192.168.188.201

4306

mysqlvm1-1

提示符為mysql4306>

 

 

5306

 

提示符為mysql5306>

 

 

6306

 

提示符為mysql6306>

 

 

7306

 

提示符為mysql7306>

 

MySQL版本

  5.7.26

 

前置條件

  已配置好主從復制。

 

配置增強半同步

  1.加載lib,所有主從節點都要配置。

    主庫&從庫:

install plugin rpl_semi_sync_master soname 'semisync_master.so';

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';   

 

      

  2.查看,確保所有節點都成功加載。

    mysql> show plugins;

      | rpl_semi_sync_master       | ACTIVE   | REPLICATION        | semisync_master.so | GPL     |

      | rpl_semi_sync_slave        | ACTIVE   | REPLICATION        | semisync_slave.so  | GPL     |

 

 

  3.啟用半同步

    1.先啟用從庫上的參數,最后啟用主庫的參數。

    從庫:

set global rpl_semi_sync_slave_enabled = 1;   # 1:啟用,0:禁止

 

    主庫:

        

set global rpl_semi_sync_master_enabled = 1;   # 1:啟用,0:禁止

set global rpl_semi_sync_master_timeout = 60000;       # 60秒,時間長些便於實驗

 

    2.從庫重啟io_thread

    stop slave io_thread;

    start slave io_thread;

 

    查看主庫參數

      

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| binlog_group_commit_sync_delay            | 100        |
| binlog_group_commit_sync_no_delay_count   | 10         |
| innodb_flush_sync                         | ON         |
| innodb_sync_array_size                    | 1          |
| innodb_sync_spin_loops                    | 30         |
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
| rpl_semi_sync_slave_trace_level           | 32         |
| sync_binlog                               | 1          |
| sync_frm                                  | ON         |
| sync_master_info                          | 10000      |
| sync_relay_log                            | 10000      |
| sync_relay_log_info                       | 10000      |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

 

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Innodb_data_fsyncs                         | 664      |
| Innodb_data_pending_fsyncs                 | 0        |
| Innodb_os_log_fsyncs                       | 413      |
| Innodb_os_log_pending_fsyncs               | 0        |
| Rpl_semi_sync_master_clients               | 4        |
| Rpl_semi_sync_master_net_avg_wait_time     | 0        |
| Rpl_semi_sync_master_net_wait_time         | 0        |
| Rpl_semi_sync_master_net_waits             | 199      |
| Rpl_semi_sync_master_no_times              | 21       |
| Rpl_semi_sync_master_no_tx                 | 48       |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_master_timefunc_failures     | 0        |
| Rpl_semi_sync_master_tx_avg_wait_time      | 3280008  |
| Rpl_semi_sync_master_tx_wait_time          | 72160195 |
| Rpl_semi_sync_master_tx_waits              | 22       |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0        |
| Rpl_semi_sync_master_wait_sessions         | 0        |
| Rpl_semi_sync_master_yes_tx                | 20       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+

19 rows in set (0.00 sec)

 

 

============================我是分割線=====================================

 

 

實驗1

場景:

  rpl_semi_sync_master_wait_no_slave=ON

  rpl_semi_sync_master_wait_for_slave_count=3

  slave存活1,其他slave停止,會發生什么?

步驟:

  1.只保留一個slave,停止其他3個slave

mysql5306> stop slave;
mysql6306> stop slave;
mysql7306> stop slave;

 

  2.立即查詢master

    為減少信息干擾,只截取了需要關注的數據

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

 

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 4        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  3.等待一分鍾,再查詢master

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

 

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 1        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  4.另外開啟一個master會話,開始一個事務並提交

mysql> insert into new values(4);
[掛起……]

 

  5.查看master

    發現無變化

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

 

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 1        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  6.查看存活的slave

    發現事務已經被應用

mysql> select * from new;

+------+
| name |
+------+
|    2 |
+------+
1 rows in set (0.00 sec)

 

 

  7.等待master事務超時后完成。

     這里master提交到收到結果,用了1分鍾0.01秒,該事務因slave的ack應答不夠,發生了等待。

mysql> insert into new values(4);
Query OK, 1 row affected (1 min 0.01 sec)

 

 

  8.查看master

    可以發現,事務超時后,master已經轉為異步復制(Rpl_semi_sync_master_status=OFF)

 

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

 

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 1        |
| Rpl_semi_sync_master_status                | OFF      |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  9.依次啟動已經停止的slave,每啟動一個,便立即查看一次master狀態

    可以看到,啟動slave的動作會立即被master接收到,並且master會自動切換回半同步模式(Rpl_semi_sync_master_status=ON)

 

mysql5306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 2        |
| Rpl_semi_sync_master_status                | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

mysql6306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 3        |
| Rpl_semi_sync_master_status                | ON       |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

mysql7306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 4        |
| Rpl_semi_sync_master_status                | ON       |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

============================我是分割線=====================================

 

實驗2

場景:

  rpl_semi_sync_master_wait_no_slave=OFF

  rpl_semi_sync_master_wait_for_slave_count=3

  slave存活1,其他slave停止,會發生什么?

步驟:

  1.繼續實驗1的環境,首先設置參數並查看master狀態

    為減少信息干擾,只截取了需要關注的數據 

mysql> set global rpl_semi_sync_master_wait_no_slave=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like "%sync%"; show global status like "%sync%";

+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 60000      |
| rpl_semi_sync_master_wait_for_slave_count | 3          |
| rpl_semi_sync_master_wait_no_slave        | OFF        |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_semi_sync_slave_enabled               | ON         |
+-------------------------------------------+------------+
18 rows in set (0.00 sec)

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 4        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  2.只保留一個slave,依次停止其他3個slave

mysql5306> stop slave;
mysql6306> stop slave;
mysql7306> stop slave;

 

 

  3.等待一分鍾,查看master狀態。(在等待期間可以通過反復查看master狀態,來觀察master數據的變化)

    master已經轉為異步模式復制。 

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 1        |
| Rpl_semi_sync_master_status                | OFF      |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

  4.使用另一個master的會話,開始一個事務並提交。 這里master提交到收到結果,該事務沒有發生等待。

mysql> insert into new values(5);
Query OK, 1 row affected (0.02 sec)

 

 

  5.立即查看存活的slave

     事務已經被應用。

mysql> select * from new;

+------+
| name |
+------+
|    4 |
|    5 |
+------+
2 rows in set (0.00 sec)

 

 

  6.依次啟動其他slave,每啟動一個便立即查看master狀態

    可以看到,啟動slave的動作會立即被master接收到,並且master會自動切換回半同步模式(Rpl_semi_sync_master_status=ON)

mysql5306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 2        |
| Rpl_semi_sync_master_status                | OFF      |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

mysql6306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 3        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

mysql7306> start slave;

mysql> show global status like "%sync%";

+--------------------------------------------+----------+
| Variable_name                              | Value    |
+--------------------------------------------+----------+
| Rpl_semi_sync_master_clients               | 4        |
| Rpl_semi_sync_master_status                | ON       |
| Rpl_semi_sync_slave_status                 | OFF      |
+--------------------------------------------+----------+
19 rows in set (0.00 sec)

 

 

============================我是分割線=====================================

結論:

使用直白簡短好理解的語言:

 

【rpl_semi_sync_master_wait_for_slave_count】

  1.master提交后所需的應答數量!如果slave clients數量大於等於這個值,那么master會一路暢行無阻;如果低於這個值,master可能會在事務提交階段發生一次超時等待,當等待超過參數(rpl_semi_sync_master_timeout)設定時,master就轉為異步模式(原理見下一個參數)。

  2.master將這個參數值作為標桿,用來和【Rpl_semi_sync_master_clients】參數做比較。

【rpl_semi_sync_master_wait_no_slave】

  1.為OFF時,只要master發現【Rpl_semi_sync_master_clients】小於【rpl_semi_sync_master_wait_for_slave_count】,則master立即轉為異步模式。

  2.為ON時,空閑時間(無事務提交)里,即使master發現【Rpl_semi_sync_master_clients】小於【rpl_semi_sync_master_wait_for_slave_count】,也不會做任何調整。只要保證在事務超時之前,master收到大於等於【rpl_semi_sync_master_wait_for_slave_count】值的ACK應答數量,master就一直保持在半同步模式;如果在事務提交階段(master等待ACK)超時,master才會轉為異步模式。

 

無論【rpl_semi_sync_master_wait_no_slave】為ON還是OFF,當slave上線到【rpl_semi_sync_master_wait_for_slave_count】值時,master都會自動由異步模式轉為半同步模式。

 

粗略看來,設置為OFF時,master不會因為slave的離線而造成事務等待,這似乎是一個更合適的選擇,但是為什么5.7中默認參數為ON呢?目前我還不得而知。

另外,本次實驗建立在空閑場景(或者說極微小負載場景)下,在高並發的場景下,這個參數又會導致怎樣的結果,這塊也尚需后續探索。

 

 

 ============================我是分割線=====================================

官方文檔關於參數rpl_semi_sync_master_wait_no_slave的解釋:

 

Controls whether the master waits for the timeout period configured by rpl_semi_sync_master_timeout to expire, even if the slave count drops to less than the number of slaves configured by pl_semi_sync_master_wait_for_slave_count during the timeout period.

 

When the value of rpl_semi_sync_master_wait_no_slave is ON (the default), it is permissible for the slave count to drop to less than rpl_semi_sync_master_wait_for_slave_count during the timeout period. As long as enough slaves acknowledge the transaction before the timeout period expires, semisynchronous replication continues.

 

When the value of rpl_semi_sync_master_wait_no_slave is OFF, if the slave count drops to less than the number configured in rpl_semi_sync_master_wait_for_slave_count at any time during the timeout period configured by rpl_semi_sync_master_timeout, the master reverts to normal replication.

 

This variable is available only if the master-side semisynchronous replication plugin is installed.

 

官方文檔關於參數rpl_semi_sync_master_wait_for_slave_count的解釋:

 

The number of slave acknowledgments the master must receive per transaction before proceeding. By default rpl_semi_sync_master_wait_for_slave_count is 1, meaning that semisynchronous replication proceeds after receiving a single slave acknowledgment. Performance is best for small values of this variable.

 

For example, if rpl_semi_sync_master_wait_for_slave_count is 2, then 2 slaves must acknowledge receipt of the transaction before the timeout period configured by rpl_semi_sync_master_timeout for semisynchronous replication to proceed. If less slaves acknowledge receipt of the transaction during the timeout period, the master reverts to normal replication.

 

 

============================我是結束線=====================================

EOF


免責聲明!

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



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