MySQL半同步複製

半同步複製簡介

MySQL複製默認情況下是異步的,主庫將事件寫入binlog並不管從庫是否接受並處理它們,如果主庫崩潰時,已提交的事務可能沒有被傳送到從庫,因此主從切換可能導致數據丟失。Semisynchronous Replication(半同步複製)則一定程度上保證提交的事務已經傳給了至少一個備庫。半同步
複製中,僅僅保證事務的已經傳遞到備庫上,但是並不確保已經在備庫上執行完成了。半同步複製確實有一定的性能影響,因爲需要等待的從庫確認。這是對增加數據的完整性的折衷。

工作原理:

  1. 從庫連接主庫時指明時從庫否有半同步能力
  2. 主庫啓動半同步複製且至少有一個半同步從庫,主庫線程執行事務提交之後將會阻塞直到任一半同步從庫確認接收到該事務的所有事件或者超時
  3. 從庫確認接收到事務的所有事件之後寫入到中繼日誌並刷新到磁盤
  4. 如果超時沒有任何從庫確認事務,主庫恢復到異步複製,保障業務的正常使用,直到一臺從庫追趕上之後,繼續切換到半同步模式
  5. 半同步複製必須主從兩端同時啓用,如任意一端禁止將使用異步複製

當主庫被阻塞時(已經提交的事務等待從從庫確認),不會向執行事務的session返回信息;當主庫阻塞結束後,返回session執行結果。
此時,主庫事務已提交,至少一臺從庫確認接收到事務。

如果主備網絡故障或者從庫崩潰,主庫在事務提交後等待10秒(rpl_semi_sync_master_timeout默認值)後,主從複製將自動降級爲異步模式。

半同步複製是通過plugin實現的,master和slave使用不同的plugin。默認情況下沒有安裝該plugin,插件位於CMAKE_INSTALL_PREFIX/lib/plugin/。安裝完插件之後,還需要手動設置系統參數以開啓半同步複製模式。

安裝配置半同步

[Master]

首先先檢查 mysql是否支持動態添加插件
mysql> show variables like 'have_dynamic_loading';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES   |
+----------------------+-------+
1 row in set (0.02 sec)

mysql>  install plugin rpl_semi_sync_master  soname 'semisync_master.so';
Query OK, 0 rows affected (0.04 sec)

mysql> show variables like '%sem%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
4 rows in set (0.00 sec)

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

mysql> set global rpl_semi_sync_master_timeout=2000;        #毫秒
Query OK, 0 rows affected (0.00 sec)


mysql> show status like '%sem%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |     # 有多少slave設置了半同步模式
| 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     |     # 一共有幾次從Semi-sync跌回普通狀態
| Rpl_semi_sync_master_no_tx                 | 0     |     # 備庫未及時響應的事務次數
| Rpl_semi_sync_master_status                | ON    |     # 主庫上Semi-sync是否正常開啓
| Rpl_semi_sync_master_timefunc_failures     | 0     |     # 時間函數未正常工作的次數
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |     # 開啓Semi-sync,事務返回需要等待的平均時間
| 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.01 sec)


[Slave]

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.03 sec)

mysql> show variables like '%sem%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

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

然後重啓replication(stop slave;start slave;)即可。
一定需要重啓,否則master無法確認該slave是否開啓了半同步。相同的操作可以在任意多個slave中進行設置。
[slave]

mysql> show status like '%sem%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.01 sec)

[master]

mysql> show status like '%sem%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 9978  |
| Rpl_semi_sync_master_net_wait_time         | 19957 |
| Rpl_semi_sync_master_net_waits             | 2     |
| Rpl_semi_sync_master_no_times              | 1     |
| Rpl_semi_sync_master_no_tx                 | 2     |
| 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)

狀態說明:
Rpl_semi_sync_master_tx_avg_wait_time:事務因開啓Semi_sync,平均需要額外等待的時間
Rpl_semi_sync_master_net_avg_wait_time:事務進入等待隊列後,到網絡平均等待時間
依據上面兩個狀態值可以知道,Semi-sync的網絡消耗有多大,給某個事務帶來的額外的消耗有多大。

Rpl_semi_sync_master_status: 表示主庫當前Semi-sync是否正常工作
Rpl_semi_sync_slave_status: 表示從庫當前Semi-sync是否正常工作

Rpl_semi_sync_master_no_times:可以知道一段時間內,Semi-sync是否有超時失敗過,該計數器則記錄了這樣的失敗次數。

Rplsemi_sync_master_wait_pos_backtraverse:在semisync_master中,維護了這樣的兩個變量wait_file_name和waitfile_pos,當主庫上多個事務都在等待從庫的響應時,這兩個變量記錄了所有等待中,最小的那一個Binlog位置。如果這時一個新的事務加入等待,並且該事務需要等待的Binlog比waitfile_name和waitfile_pos還小的話,則更新這兩個值,並將Rpl_semi_sync_master_wait_pos_backtraverse值自增1。

整理自網絡

Svoid
2015-01-29
發佈了54 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章