天天看點

[MySQL 5.6] Innodb并發控制改進

從5.6開始,如果使用了gcc build-in的原子操作,在進入innodb層的線程并發控制走與之前不同的邏輯,5.5也可以調用通過原子操作進行并發控制的邏輯,但需要打開隻讀選項innodb_thread_concurrency_timer_based來控制.

quoted code in 5.6:

srv_conc_enter_innodb_without_atomics是mysql5.5的調用邏輯,在5.6中開始預設編譯情況下,調用srv_conc_enter_innodb_with_atomics邏輯,其不同之處在于使用gcc build-in的原子操作,來避免熱點鎖srv_conc_mutex的頻繁加鎖/釋放。

原先的做法是在進入innodb層前,先檢視目前在innodb中活躍的線程數是否超過innodb_thread_concurrency; 如果超過了,則sleep一段時間,再重試,如果還是超過并發限制時,就給其配置設定一個slot,讓其進入信号量等待。

在5.6中,當使用原子操作進行并發控制時,如果innodb_adaptive_max_sleep_delay大于0, 會對另外一個參數innodb_thread_sleep_delay的值做自适應調整.它的邏輯也很簡單。

我們這裡假定innodb_adaptive_max_sleep_delay的值大于0 

當線程能夠進入innodb層時:

a.如果目前線程之前sleep過一次,并且目前innodb_thread_sleep_delay>20,将innodb_thread_sleep_delay減1

b.如果目前沒有等待的線程,将innodb_thread_sleep_delay除以2

如果線程目前因并發控制無法進入innodb層:

a.如果目前innodb_thread_sleep_delay>innodb_adaptive_max_sleep_delay

,将innodb_thread_sleep_delay的值設定為innodb_adaptive_max_sleep_delay

b.sleep  innodb_thread_sleep_delay毫秒

c.如果該線程已經sleep了超過1次,将innodb_thread_sleep_delay++

可以看到innodb_thread_sleep_delay降低比增加的更快。這樣在并發線程數很高時,當限制并發數早就達到,其他線程的每次sleep時間會緩慢拉長。而當innodb層很空閑時,sleep時間又會快速降到非常低

調整sleep到一個優化值的目的是,過小的sleep值可能會産生太多的線程切換,但過長的sleep時間,在并發比較空閑的時候又會影響性能。新的并發控制政策有利于随着負載的變化而做自适應調整。

另外注意,在使用原子操作進行并發控制後,就再也沒有使用信号量讓線程進行等待了。

這種自适應調整政策的效率依然有待于評估,也不确定其對某些工作負載是否存在不利影響。合适的參數配置應當由性能測試來給出。

繼續閱讀