最近碰到壹個問題,線上壹臺機器在等待信號量時間過長,,mysql的監控線程認為此時mysqld已經hang住了,於是自殺重啟。這裏涉及到壹個有趣的問題,也就是mysql如何對讀寫鎖進行處理。
主要包括三個部分:
1. 建鎖
2. 加鎖
3. 解鎖
4. 監控鎖
以下內容基於Percona5.5.18進行分析
1.創建鎖
鎖的創建實際上就是初始化壹個RW結構體(rw_lock_t),實際調用函數如下:
[cpp]
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L),#L)
在rw_lock_create上有三個參數,在實際場景鎖時只用到第2個參數
其中K表示mysql_pfs_key_t,level顯示當前的操作類型(起碼看起來是的,在文件sync0sync.h中定義),看起來k是為performance schema準備的,而k代表了當前操作所在的層次。
例如:purge線程的讀寫鎖創建:
[html]
rw_lock_create(trx_purge_latch_key,
我們進去rw_lock_create_func看看到底是怎麽創建的。
可以看到這個函數的邏輯其實很簡單:
lock->lock_word =X_LOCK_DECR; //關鍵字段
用於限制讀寫鎖的最大並發數,代碼裏的註釋如下:
[cpp]
在嘗試加鎖時會調用rw_lock_lock_word_decr減少lock_word
在初始化壹系列變量後,執行:
[cpp]
lock->event = os_event_create(NULL);
lock->wait_ex_event = os_event_create(NULL);
os_event_create用於創建壹個系統信號,實際上最終創建的還是互斥量(os_fast_mutex_init(&(event->os_mutex));以及條件變量(os_cond_init(&(event->cond_var));)
最後將lock加入到全局鏈表rw_lock_list中