異步複製
,可是異步複製的不足之處就在於,當主庫把event寫入二進制日誌以後,並不知道從庫是否已經接收並應用了。在異步模式的複製,若是主庫崩潰,頗有可能在主庫中已經提交的事務,並無傳到到任何一臺從庫機器上。在高可用集羣架構下作主備切換,就會形成新的主庫丟失數據的現象。
MySQL5.5版本以後引入了半同步複製功能,主從服務器必須同時安裝半同步複製插件,才能開啓該複製功能。在該功能下,確保從庫接收完主庫傳遞過來的binlog內容已經寫入到本身的relay log裏,纔會通知主庫上的等待線程,該操做完畢。若是等待超時,超過repl_semi_sync_master_timeout
參數設置的時間,則關閉半同步複製,並自動轉換爲異步複製
模式,直到至少有一臺從庫通知主庫已經接收到binlog信息爲止。php
半同步複製提高了主從之間數據的一致性,讓複製更加安全可靠。在MySQL5.7.2版本中增長了rpl_semi_sync_master_wait_point
參數,用來控制半同步模式下主庫返回給session事務成功以前的事務提交方式。python
該參數有兩個值:mysql
AFTER_COMMIT(MySQL5.6默認值)
主庫將每一個事務寫入binlog,並傳遞給從庫,刷新到中繼日誌中,同時主庫提交事務,以後主庫開始等待從庫的反饋,只有收到從庫的回覆以後,master纔將commit OK
的結果反饋給客戶端。web
AFTER_SYNC(MySQL5.7默認值)
主庫將每一個事務寫入binlog,並傳遞給從庫,刷新到中繼日誌中,主庫開始等待從庫的反饋,接收到從庫的回覆以後,再提交事務而且返回commit OK
結果給客戶端。sql
能夠經過
repl_semi_sync_master_wait_for_slave_count
參數來控制主庫接收多少個從庫寫事務成功反饋,才返回成功給客戶端。生產環境中使用半同步複製方式,當從庫出現故障,等待超時的時間又很長,致使主庫沒法接收從庫信息而沒法正常寫入時,可經過該參數剔除故障從庫。數據庫
在AFTER_SYNC模式下,即便主庫宕機,全部在主庫上已經提交的事務都能保證已經同步到從庫的中繼日誌中,不會丟失任何數據。安全
半同步複製的安裝很是簡單,它基於異步複製的基礎上,安裝半同步複製插件。服務器
在master上:session
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%'; +----------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +----------------------+---------------+ | rpl_semi_sync_master | ACTIVE | +----------------------+---------------+
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%'; +----------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +----------------------+---------------+ | rpl_semi_sync_master | ACTIVE | +----------------------+---------------+
在slave上架構
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%'; +---------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +---------------------+---------------+ | rpl_semi_sync_slave | ACTIVE | +---------------------+---------------+
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%'; +---------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +---------------------+---------------+ | rpl_semi_sync_slave | ACTIVE | +---------------------+---------------+
安裝了半同步複製插件後,默認狀況下會禁用它。必須在master和slave上都啓用插件才能啓用半同步複製。若是僅啓用一側,則複製將是異步的。
要控制是否已啓用已安裝的插件,請設置相應的系統變量。能夠在運行時使用SET GLOBAL
或`在命令行或選項(my.cnf)文件中的服務器啓動時設置這些變量。
在複製運行時,master可用的系統變量:
SET GLOBAL rpl_semi_sync_master_enabled = {0|1}; SET GLOBAL rpl_semi_sync_master_timeout = N;
SET GLOBAL rpl_semi_sync_master_enabled = {0|1}; SET GLOBAL rpl_semi_sync_master_timeout = N;
在複製運行時,slave可用的系統變量
SET GLOBAL rpl_semi_sync_slave_enabled = {0|1};
SET GLOBAL rpl_semi_sync_slave_enabled = {0|1};
對於 rpl_semi_sync_master_enabled
或 rpl_semi_sync_slave_enabled
,該值應爲1以啓用半同步複製,或者爲0以禁用它。默認狀況下,這些變量設置爲0。
對於 rpl_semi_sync_master_timeout
,值N以毫秒爲單位。默認值爲10000(10秒)。
激活半同步複製,須要重啓從庫的I/O線程
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
操做以下:
#master上 mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1; mysql> SET GLOBAL rpl_semi_sync_master_timeout = 60000;#該參數默認值是10s,應儘可能調整大點,減少向異步複製切換以保證數據複製的安全性。 #要在服務器啓動時,啓動半同步複製,能夠在my.cnf文件添加以下 [mysqld] rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=60000 # 60 second #slave上 mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1; mysql> STOP SLAVE IO_THREAD; mysql> START SLAVE IO_THREAD; #要在服務器啓動時,啓動半同步複製,能夠在my.cnf文件添加以下 [mysqld] rpl_semi_sync_slave_enabled=1
#master上 mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1; mysql> SET GLOBAL rpl_semi_sync_master_timeout = 60000;#該參數默認值是10s,應儘可能調整大點,減少向異步複製切換以保證數據複製的安全性。 #要在服務器啓動時,啓動半同步複製,能夠在my.cnf文件添加以下 [mysqld] rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=60000 # 60 second #slave上 mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1; mysql> STOP SLAVE IO_THREAD; mysql> START SLAVE IO_THREAD; #要在服務器啓動時,啓動半同步複製,能夠在my.cnf文件添加以下 [mysqld] rpl_semi_sync_slave_enabled=1
半同步複製功能的插件公開了幾個系統和狀態變量,能夠檢查這些變量以肯定其配置和運行狀態。
系統變量反映瞭如何配置半同步複製。要檢查其值,請使用SHOW VARIABLES
:
#master mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | 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 | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | +-------------------------------------------+------------+ 6 rows in set (0.00 sec) #slave mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.00 sec)
#master mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | 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 | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | +-------------------------------------------+------------+ 6 rows in set (0.00 sec) #slave mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.00 sec)
狀態變量能夠監視半同步複製的操做。要檢查其值,請使用SHOW STATUS
:
#master mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +--------------------------------------------+-------+ | 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) #slave mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
#master mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +--------------------------------------------+-------+ | 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) #slave mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
在master端:
Rpl_semi_sync_master_status
:此狀態變量用來肯定主服務器當前是使用異步仍是半同步複製
Rpl_semi_sync_master_clients
:查看鏈接了多少個半同步slave
Rpl_semi_sync_master_no_tx
:表明沒有成功接收slave事務提交回復的次數
Rpl_semi_sync_master_yes_tx
:表明成功接收slave事務提交回復的次數
Rpl_semi_sync_master_net_avg_wait_time
:主機等待slave回覆的平均時間(以微秒爲單位)。此變量已棄用,始終爲0,將在之後的版本中刪除。
Rpl_semi_sync_master_net_wait_time
:主機等待slave回覆的總時間(以微秒爲單位)。此變量已棄用,始終爲0,將在之後的版本中刪除。
Rpl_semi_sync_master_net_waits
:master等待slave回覆的總次數。
Rpl_semi_sync_master_no_times
:主服務器關閉半同步複製的次數。
Rpl_semi_sync_master_timefunc_failures
:調用gettimeofday()
等時間函數時主服務器失敗的次數。
Rpl_semi_sync_master_tx_avg_wait_time
:master等待每一個事務的平均時間(以微秒爲單位)。
Rpl_semi_sync_master_tx_wait_time
:master等待事務的總時間(以微秒爲單位)。
Rpl_semi_sync_master_tx_waits
:主服務器等待事務的總次數。
Rpl_semi_sync_master_wait_pos_backtraverse
:master等待二進制座標低於先前等待事件的事件的總次數。當事務開始等待回覆的順序與其二進制日誌事件的寫入順序不一樣時,就會發生這種狀況。
Rpl_semi_sync_master_wait_sessions
:當前正在等待slave回覆的會話數。
在slave端:
Rpl_semi_sync_slave_status
:指示半同步複製當前是否可操做。
半同步複製的原理是從庫的I/O thread接收完主庫的binlog,並把它寫入relay中後,會給主庫一個回饋。但若是主庫等待從庫的回饋時間超過repl_semi_sync_master_timeout
參數設置的時間,會自動切換爲異步複製方式。
下面就利用rpl_semi_sync_master_timeout
超時設置,測試半同步複製與異步複製的切換。
#1. 查看主庫rpl_semi_sync_master_timeout設置時間 root@localhost [(none)] 15:45:06> show variables like '%rpl_semi_sync_master_tim%'; +------------------------------+-------+ | Variable_name | Value | +------------------------------+-------+ | rpl_semi_sync_master_timeout | 60000 | +------------------------------+-------+ 1 row in set (0.00 sec) #2. 從庫關掉I/O thread線程 root@localhost [(none)] 15:02:14>stop slave io_thread; #3. 查看從庫的半同步狀態,爲OFF root@localhost [(none)] 15:46:49>show global status like '%semi%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | OFF | +----------------------------+-------+ 1 row in set (0.00 sec) #4. 查看主庫的半同步複製狀態 root@localhost [(none)] 15:58:03> show global status like '%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) #主庫第一次插入耗時60s root@localhost [test] 15:59:05> insert into z1 values(4,'python'); Query OK, 1 row affected (1 min 0.01 sec) #主庫第二次插入耗時0.01s root@localhost [test] 16:00:25> insert into z1 values(5,'php'); Query OK, 1 row affected (0.01 sec) # 主庫查看半同步狀態 root@localhost [test] 16:07:04> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 2 | | Rpl_semi_sync_master_no_tx | 3 | | Rpl_semi_sync_master_status | OFF | | 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) 【說明】 第一次插入時,主庫一直在等待從庫的回覆(60s),直到超過60s,主庫再進行提交,且轉換爲異步複製。 第二次插入時,主從庫已爲異步複製,因此插入無需等待從庫的反饋。
#1. 查看主庫rpl_semi_sync_master_timeout設置時間 root@localhost [(none)] 15:45:06> show variables like '%rpl_semi_sync_master_tim%'; +------------------------------+-------+ | Variable_name | Value | +------------------------------+-------+ | rpl_semi_sync_master_timeout | 60000 | +------------------------------+-------+ 1 row in set (0.00 sec) #2. 從庫關掉I/O thread線程 root@localhost [(none)] 15:02:14>stop slave io_thread; #3. 查看從庫的半同步狀態,爲OFF root@localhost [(none)] 15:46:49>show global status like '%semi%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | OFF | +----------------------------+-------+ 1 row in set (0.00 sec) #4. 查看主庫的半同步複製狀態 root@localhost [(none)] 15:58:03> show global status like '%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) #主庫第一次插入耗時60s root@localhost [test] 15:59:05> insert into z1 values(4,'python'); Query OK, 1 row affected (1 min 0.01 sec) #主庫第二次插入耗時0.01s root@localhost [test] 16:00:25> insert into z1 values(5,'php'); Query OK, 1 row affected (0.01 sec) # 主庫查看半同步狀態 root@localhost [test] 16:07:04> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 2 | | Rpl_semi_sync_master_no_tx | 3 | | Rpl_semi_sync_master_status | OFF | | 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) 【說明】 第一次插入時,主庫一直在等待從庫的回覆(60s),直到超過60s,主庫再進行提交,且轉換爲異步複製。 第二次插入時,主從庫已爲異步複製,因此插入無需等待從庫的反饋。