在MySQL5.5之前的版本中,MySQL的復制是異步復制,主庫和從庫的數據之間存在一定的延遲,比如網絡故障等各種原因,這樣子容易存在隱患就是:當在主庫寫入一個事務成功后並提交了,但是由於從庫延遲沒有及時得到主庫推送的Binlog日志時,主庫突然宕機了,那么此時從庫就可能損失這個事務,從而造成主從不一致的狀況。
因此我們MySQL5.5版本之后引入了半同步復制的概念
半同步復制的原理:
半同步復制時,為了保證主庫上的每一個Binlog事務都能夠被可靠的復制到從庫上,主庫在每次事務成功提交時,並不及時反饋給前端應用用戶,而是等待其中的一個從庫也接收到Binlog事務並成功寫入中繼日志后,出庫才返回commit操作成功給客戶端。半同步復制保證了事務成功提交后,至少有兩份日志記錄,一份在主庫的Binlog日志上,另一份在至少一個從庫的中繼日志Relay log上,從而更近一步保證了數據的完整性。

這個示意圖是半同步復制的步驟:
在這個半同步復制模式下:第1、2、3中任何一個步驟中主庫宕機,則事務並沒有提交成功。從庫也沒有得到日志,此時的主從復制數據是一致的。
那什么時候半同步復制會突然變成異步復制呢?
在第4步的時候,如果網絡延遲故障或從庫宕機,那么此時主庫的Binlog都沒有及時傳送給從庫上,此時主庫上的事務會等待一段時間,時間長短由參數rpl_semi_master_timeout設置的毫秒數來決定,如果Binlog在這段時間內都無法成功推送到從庫上,則MySQL自動調整復制模式為異步模式,此時事務正常返回提交結果給客戶端。
半同步復制很大程度上取決於主從庫之間的網絡情況,往返時延RTT越小決定了從庫的實時性越好。
搭建步驟:
這次我們使用一個master節點兩個slave節點進行搭建,並且進行此實驗之前我們已經搭建好異步復制的環境了。搭建半同步復制不過是在異步的基礎上添加一些插件而已。
| 172.31.22.29 | master |
| 172.31.26.133 | slave |
| 172.31.17.203 | slave |
1、首先判斷一下當前版本的數據庫是否支持動態擴展,因為我們的版本都是一致的,因此在一台機器上檢查即可
mysql> select @@have_dynamic_loading; +------------------------+ | @@have_dynamic_loading | +------------------------+ | YES | +------------------------+ 1 row in set (0.00 sec)
2、確認支持動態增加插件以后,我們再來檢查一下MySQL的$MYSQL/lib/plugin目錄下是否存在主庫插件“semisync_master.so”和從庫插件“semisync_slave.so”。
[root@:vg_adn_tidbCkhsTest /usr/local/mysql/lib/plugin]#ls #這里只列出了一部分而已 adt_null.so libtest_framework.so libtest_sql_lock.so mysqlx.so authentication_ldap_sasl_client.so libtest_services.so libtest_sql_processlist.so rewrite_example.so auth_socket.so libtest_services_threaded.so libtest_sql_replication.so rewriter.so connection_control.so libtest_session_detach.so libtest_sql_shutdown.so semisync_master.so debug libtest_session_info.so libtest_sql_sqlmode.so semisync_slave.so group_replication.so libtest_session_in_thd.so libtest_sql_stored_procedures_functions.so test_security_context.so
接下來我們在主庫上安裝插件
mysql> install plugin rpl_semi_sync_master SONAME 'semisync_master.so'; Query OK, 0 rows affected (0.00 sec)
在兩個從庫上安裝插件
MySQL [(none)]> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.01 sec)
安裝完成后,我們可以使用語句來查看一下:
mysql> select * from mysql.plugin; +----------------------+--------------------+ | name | dl | +----------------------+--------------------+ | rpl_semi_sync_master | semisync_master.so | +----------------------+--------------------+ 1 row in set (0.00 sec)
說明我們已經安裝插件成功了。並且系統重啟的時候也會自動加載該插件,不必擔心。
3、現在我們需要分別在主庫和從庫上配置參數打開半同步semi-sync,默認情況下半同步設置不打開的,主庫上配置全局參數。
mysql> set global rpl_semi_sync_master_enabled=1; Query OK, 0 rows affected (0.00 sec) mysql> set global rpl_semi_sync_master_timeout=10000; #注意這是毫秒單位,因此這個數是10秒。 Query OK, 0 rows affected (0.00 sec)
兩個從庫上也需要配置:
MySQL [(none)]> set global rpl_semi_sync_slave_enabled=1; Query OK, 0 rows affected (0.00 sec)
注意:由於之前已經配置過異步復制,因此在這里需要重啟一下從庫上的I/O線程。(如果是全新配置的半同步復制則不需要這一步驟。)
MySQL [(none)]> stop slave io_thread; Query OK, 0 rows affected (0.00 sec) MySQL [(none)]> start slave io_thread; Query OK, 0 rows affected (0.00 sec)
有幾台slave,就在幾台上執行這樣子的操作。到此,半同步復制就搭建成功了。
在主庫上使用下面命令執行以下看看半同步復制的狀態信息:
mysql> show status like '%semi_sync%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 2 | | 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)
我們注重關注這三個值:
1、Rpl_semi_sync_master_status:值為ON,表示半同步復制目前處於打開狀態。
2、Rpl_semi_sync_master_no_tx:這個值表示當前主庫有多少個事務不是半同步模式下從庫及時響應的。
3、Rpl_semi_sync_master_yes_tx:這個值表示當前主庫上有多少個事務是通過半同步復制到從庫的。
在日常的維護中,我們可以查看着三項值判斷半同步復制是否是正常的。
