semi-sync原主庫加入叢集阻塞問題分析

沃趣科技發表於2016-11-16

沃趣科技  彭許生



前段時間支援客戶處理問題的時候,發現一個semi-sync複製主從切換原master加入叢集時,複製同步阻塞,無法繼續同步資料的問題,非常有參考意義,整理一下,供大家參考。

問題現象

客戶在一個一主兩從的半同步複製環境下做了手工切換,然後嘗試把原主庫加入叢集中,結果發現新叢集中的資料一直無法同步到slave(原主庫)中來,檢視slave(原主庫)同步狀態,IO執行緒和SQL執行緒都是YES狀態,但是Seconds_Behind_Master大於0.

  1. mysql> show slave status\G
  2. *************************** 1. row ***************************
  3. Slave_IO_State: Waiting for master to send event
  4. ..............................................
  5. Master_Log_File: mysql-bin.000007
  6. Read_Master_Log_Pos: 540
  7. Relay_Log_File: mysql-relay-bin.000006
  8. Relay_Log_Pos: 367
  9. Relay_Master_Log_File: mysql-bin.000007
  10. Slave_IO_Running: Yes
  11. Slave_SQL_Running: Yes
  12. ..............................................
  13. Seconds_Behind_Master: 1145
  14. Slave_SQL_Running_State: Waiting for semi-sync ACK from slave
  15. 1 row in set (0.00 sec)

檢視show processlist狀態, 發現SQL執行緒一直處於Waiting for semi-sync ACK from slave狀態,可是這個slave(原主庫)下已經沒有從庫了。為什麼還需要等待slave返回的ACK呢?

  1. mysql> show processlist;
  2. +----+-------------+-----------+------+---------+------+--------------------------------------+------------------+
  3. | Id | User | Host | db | Command | Time | State | Info |
  4. +----+-------------+-----------+------+---------+------+--------------------------------------+------------------+
  5. | 1 | system user | | NULL | Connect | 540 | Waiting for semi-sync ACK from slave | NULL |
  6. | 2 | system user | | NULL | Connect | 2191 | Waiting for master to send event | NULL |
  7. | 4 | root | localhost | test | Query | 0 | starting | show processlist |
  8. +----+-------------+-----------+------+---------+------+--------------------------------------+------------------+
  9. 3 rows in set (0.00 sec)

問題分析

從SQL執行緒等待的的半同步問題出發,先檢視semi-sync狀態和設定

  1. mysql> show global status like 'rpl_semi_sync%';
  2. +--------------------------------------------+-------+
  3. | Variable_name | Value |
  4. +--------------------------------------------+-------+
  5. | Rpl_semi_sync_master_clients | 0 |
  6. | Rpl_semi_sync_master_net_avg_wait_time | 0 |
  7. | Rpl_semi_sync_master_net_wait_time | 0 |
  8. | Rpl_semi_sync_master_net_waits | 0 |
  9. | Rpl_semi_sync_master_no_times | 0 |
  10. | Rpl_semi_sync_master_no_tx | 0 |
  11. | Rpl_semi_sync_master_status | ON |
  12. | Rpl_semi_sync_master_timefunc_failures | 0 |
  13. | Rpl_semi_sync_master_tx_avg_wait_time | 0 |
  14. | Rpl_semi_sync_master_tx_wait_time | 0 |
  15. | Rpl_semi_sync_master_tx_waits | 0 |
  16. | Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
  17. | Rpl_semi_sync_master_wait_sessions | 0 |
  18. | Rpl_semi_sync_master_yes_tx | 0 |
  19. | Rpl_semi_sync_slave_status | ON |
  20. +--------------------------------------------+-------+
  21. 15 rows in set (0.00 sec)

透過上面semi-sync的狀態變數,可以發現semi-sync執行狀態Rpl_semi_sync_master_status=ON、Rpl_semi_sync_slave_status=ON。這裡最奇怪的是Rpl_semi_sync_master_status=ON。

根據半同步複製原理:主庫發生資料變更寫binlog,然後等待從庫接收並返回ACK,最後在儲存引擎層提交資料。這也就是為什麼在從庫(原主庫)一直查不到新主庫變更後的資料原因。在預設情況下,半同步複製只有在等待ACK超出 rpl_semi_sync_master_timeout設定的時間才會自動降為非同步複製。

這裡slave(原主庫)被認為是半同步的master,但是沒有從庫連線他,所以一直在等待從庫返回的ACK。等待的時間我們檢視rpl_semi_sync_master_timeout變數取值

  1. mysql> show global variables like 'rpl_semi_sync%';
  2. +-------------------------------------------+------------+
  3. | Variable_name | Value |
  4. +-------------------------------------------+------------+
  5. | rpl_semi_sync_master_enabled | ON |
  6. | rpl_semi_sync_master_timeout | 10000000 |
  7. | rpl_semi_sync_master_trace_level | 32 |
  8. | rpl_semi_sync_master_wait_for_slave_count | 1 |
  9. | rpl_semi_sync_master_wait_no_slave | ON |
  10. | rpl_semi_sync_master_wait_point | AFTER_SYNC |
  11. | rpl_semi_sync_slave_enabled | ON |
  12. | rpl_semi_sync_slave_trace_level | 32 |
  13. +-------------------------------------------+------------+
  14. 8 rows in set (0.00 sec)

檢視semi-sync引數發現從庫同時開啟了rpl_semi_sync_master_enabled=ON、rpl_semi_sync_slave_enabled=ON和rpl_semi_sync_master_timeout=10000000(1萬秒,預設10秒)。

客戶竟然把rpl_semi_sync_master_timeout設定為10萬秒,也就是說,原主庫要等待10萬秒才能自動變為非同步並加入叢集中同步資料,slave(原主庫)無法從叢集中繼續同步資料的根本原因就在這裡。

跟客戶溝通後,客戶之所以將rpl_semi_sync_master_timeout設定這麼大的值,是強調資料強一致性,不希望在任何情況下半同步複製結構降為非同步複製,最大限度保證資料一致性。

原理分析

前面涉及到幾個sc 複製引數,可能有些同學不太瞭解,下面給大家簡單講解一下MySQL semi-sync 複製安裝配置和原理。 
在MySQL 5.7版本里如果要開啟半同步複製,需要在master端安裝semisync_master.so庫並配置my.cnf

  1. mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
  2. mysql> set global rpl_semi_sync_master_enabled=ON;

在slave端安裝semisync_slave.so庫並配置my.cnf

  1. mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
  2. mysql> set global rpl_semi_sync_slave_enabled=ON;
  • 在master端看到Rpl_semi_sync_master_status狀態變數顯示ON狀態,就表示master進入半同步複製模式。
  1. mysql> show global status like 'rpl_semi_sync_master_status';
  2. +-----------------------------+-------+
  3. | Variable_name | Value |
  4. +-----------------------------+-------+
  5. | Rpl_semi_sync_master_status | ON |
  6. +-----------------------------+-------+
  • 此時,在slave端會看到Rpl_semi_sync_slave_status顯示ON狀態,也就表示slave進入半同步複製模式。
  1. mysql> show global status like 'rpl_semi_sync_slave_status';
  2. +-----------------------------+-------+
  3. | Variable_name | Value |
  4. +-----------------------------+-------+
  5. | Rpl_semi_sync_slave_status | ON |
  6. +-----------------------------+-------+

進入半同步複製,客戶端在master每提交一個事務,master MySQL將對應事務寫入binlog,然後等待slave返回的ACK,之後在儲存引擎層提交,最後返回給客戶端寫入成功的訊息。 
如果slave沒有返回,master將等待指定超時時間;超過超時時間後,會自動降為非同步複製模式。
 

  • 如果master在超時時間內(rpl_semi_sync_master_timeout超時時間,預設10000毫秒)沒有收到指定數量(rpl_semi_sync_master_wait_for_slave_count接收slave返回ACK數量,預設1)的slave的ACK回包,master自動降為非同步複製模式。
  • 當半同步複製降為非同步複製模式,在master端可以看到Rpl_semi_sync_master_status=OFF,在save端可以看到Rpl_semi_sync_slave_status=OFF。
  • 上述master等待行為都發生在rpl_semi_sync_master_wait_no_slave=ON(預設值)情況下。如果rpl_semi_sync_master_wait_no_slave設定為OFF時,連線master的slave的數量少於rpl_semi_sync_master_wait_for_slave_count設定的值,master不會等待超時,立刻自動降為非同步複製模式。

    建議

    如果把rpl_semi_sync_master_timeout設定非常大,在主從切換時導致原主庫加入叢集時同步阻塞,建議把rpl_semi_sync_master_wait_no_slave=OFF。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-2128548/,如需轉載,請註明出處,否則將追究法律責任。

相關文章