mysql併發執行緒控制之innodb_thread_concurrency的改進
innodb_thread_concurrency演算法介紹:
1、server層到innodb層讀寫資料是一條一條記錄進行的,每次讀寫都會進/出一次InnoDB層(row_search_for_mysql),進入InnoDB層的時候會檢查當前併發執行緒數目,當超過innodb_thread_concurrency時,執行緒將嘗試spin和sleep並再次檢查,如果併發數還是超過innodb_thread_concurrency,執行緒將進入到一個FIFO中等待被喚醒,讀寫記錄結束後退出InnoDB層時會將當前併發執行緒數減1,並檢查其是否低於innodb_thread_concurrency,如果是的話,從FIFO中喚醒一個等待的執行緒,保證併發執行緒不會超過innodb_thread_concurrency引數。
2、當執行緒進入InnoDB層後,但在獲取資料時由於鎖請求無法得到滿足而需要掛起時,執行緒將強制退出InnoDB層,當鎖請求滿足後,執行緒繼續執行並強制進入到InnoDB層,這會導致實際併發執行緒數不是嚴格控制在innodb_thread_concurrency之內
程式碼呼叫邏輯
主要函式:
innodb_srv_conc_enter_innodb
innodb_srv_conc_exit_innodb
srv_conc_force_enter_innodb
srv_conc_force_exit_innodb
呼叫邏輯
進入/退出InnoDB層
ha_innobase::index_read
ha_innobase::general_fetch
row_check_index_for_mysql
...
innodb_srv_conc_enter_innodb(prebuilt->trx);
ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0);
innodb_srv_conc_exit_innodb(prebuilt->trx);
...
鎖等待邏輯:
srv_suspend_mysql_thread
...
if (trx->declared_to_be_inside_innodb) {
was_declared_inside_innodb = TRUE;
/* We must declare this OS thread to exit InnoDB, since a
possible other thread holding a lock which this thread waits
for must be allowed to enter, sooner or later */
srv_conc_force_exit_innodb(trx);
}
/* Suspend this thread and wait for the event. */
thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_LOCK);
os_event_wait(event);
thd_wait_end(trx->mysql_thd);
if (was_declared_inside_innodb) {
/* Return back inside InnoDB */
srv_conc_force_enter_innodb(trx);
}
5.6的改進
從5.6開始,預設編譯會使用GCC atomic,可避免熱點鎖srv_conc_mutex的頻繁加鎖/釋放。
Pre-5.5如果超過併發限制時,就給其執行緒分配一個slot,讓其進入訊號量等待,原子操作則無需使用訊號量。
function srv_conc_enter_innodb:
ifdef HAVE_ATOMIC_BUILTINS
srv_conc_enter_innodb_with_atomics(trx);
#else
srv_conc_enter_innodb_without_atomics(trx);
#endif /* HAVE_ATOMIC_BUILTINS */
5.6引入adaptive sleep,允許innodb根據系統負載進行自適應調整,當innodb_adaptive_max_sleep_delay>0, innodb_thread_sleep_delay則 會動態調整(以前者為上限)。
ada還ptive 的演算法是:
如果sleep了當前值以後還是不能進入,就把sleep時間+1;
如果還有執行緒在sleep時,已經有了空閒執行緒,就把當前值的sleep 時間減半。
innodb_thread_sleep_delay降低比增加的更快,這樣在併發執行緒數很高時,當限制併發數早就達到,其他執行緒的每次sleep時間會緩慢拉長。而當Innodb層很空閒時,sleep時間又會快速降到非常低
調整sleep到一個最佳化值的目的是,過小的sleep值可能會產生太多的執行緒切換,但過長的sleep時間,在併發比較空閒的時候又會影響效能。新的併發控制策略有利於隨著負載的變化而做自適應調整。
Innodb_thread_concurrency不足
1執行緒因為鎖等待而退出innodb層,當獲取鎖時可以直接重入innodb(跳過此引數檢查),因此係統併發執行的執行緒數可能大於此引數值。
2程式碼路徑靠後,此時執行緒已經開始執行命令,進入到ha_innobase,應該在mysql_start_query前限制即thread_running。
為此好多技術高手開發了相應patch,從server層控制併發執行的執行緒數,下文將做描述。
參考文章
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-1452232/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql併發執行緒控制之控制thread_running數量MySql執行緒thread
- mysql併發執行緒控制之thread pool和優先佇列MySql執行緒thread佇列
- MySQL 配置InnoDB的併發執行緒MySql執行緒
- 五、併發控制(1):執行緒的互斥執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- 20170526-27關於GCD控制執行緒併發數,多執行緒併發數控制GC執行緒
- 併發工具類(三)控制併發執行緒的數量 Semphore執行緒
- golang 限流器,控制併發,執行緒池Golang執行緒
- MySQL多執行緒併發調優MySql執行緒
- 執行緒控制之休眠執行緒執行緒
- 多執行緒-執行緒控制之休眠執行緒執行緒
- 多執行緒-執行緒控制之加入執行緒執行緒
- 多執行緒-執行緒控制之禮讓執行緒執行緒
- 併發程式設計之:執行緒程式設計執行緒
- Java併發程式設計之執行緒篇之執行緒的由來(一)Java程式設計執行緒
- Go高效併發 10 | Context:多執行緒併發控制神器GoContext執行緒
- 多執行緒-執行緒控制之守護執行緒執行緒
- Java併發程式設計之執行緒篇之執行緒中斷(三)Java程式設計執行緒
- Java併發程式設計之執行緒篇之執行緒簡介(二)Java程式設計執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- Java併發 之 執行緒池系列 (1) 讓多執行緒不再坑爹的執行緒池Java執行緒
- shell佇列實現執行緒併發控制(轉)佇列執行緒
- 多執行緒併發篇——如何停止執行緒執行緒
- Java多執行緒與併發之ThreadLocalJava執行緒thread
- java併發筆記之java執行緒模型Java筆記執行緒模型
- 併發程式設計之:執行緒池(一)程式設計執行緒
- Java學習之併發多執行緒理解Java執行緒
- 66.QT-執行緒併發、QTcpServer併發、QThreadPool執行緒池QT執行緒TCPServerthread
- Java併發(一)----程式、執行緒、並行、併發Java執行緒並行
- Java進階篇:多執行緒併發實踐Java執行緒
- 【重學Java】多執行緒進階(執行緒池、原子性、併發工具類)Java執行緒
- Java併發(四)----執行緒執行原理Java執行緒
- 【多執行緒與高併發】從一則招聘資訊進入多執行緒的世界執行緒
- JAVA多執行緒併發Java執行緒
- java併發與執行緒Java執行緒
- 執行緒併發總結執行緒
- [Java併發]執行緒的並行等待Java執行緒並行
- 併發程式設計之多執行緒執行緒安全程式設計執行緒