innodb_thread_concurrency
如果參數設置大於0,則表示檢查機制開啟,允許進入的線程數就是參數的值.
在新的MySQL線程調用Innodb接口前,Innodb會檢查已經接受的請求線程數;
如已經超過innodb_thread_concurrency設置的限制,則該請求線程會等待innodb_thread_sleep_delay微秒後嘗試重新請求,如果第二次請求還是無法獲得,則該線程會進入FIFO隊列休眠。重試兩次的機制是為了減少CPU的上下文切換的次數,以降低CPU消耗。
如果請求被Innodb接受,則會獲得一個次數為innodb_concurrency_tickets(默認500次)的通行證,在次數用完之前,該線程重新請求時無須再進行前面的檢查
--代碼結構如下
if (thread->n_tickets_to_enter_innodb > 0)
{
thread->n_tickets_to_enter_innodb--;
ENTER;
}
retry:
if (entered_thread < innodb_thread_concurrency)
{
entered_threads++;
thread->n_tickets_to_enter_innodb = innodb_concurrency_tickets;
ENTER;
}
if (innodb_thread_sleep_delay > 0)
{
thread_sleep(innodb_thread_sleep_delay);
}
goto retry; // (only once)
WAIT_IN_FIFO_QUEUE;
thread->n_tickets_to_enter_innodb = innodb_concurrency_tickets;
ENTER;
源文件為srv_conc_enter_innodb (innobase/srv/srv0srv).
如果是一個已經持有lock的線程,則通過調用srv_conc_force_enter_innodb函數可以無視該檢查,這是為了避免線程長時間持有鎖影響性能,且可能增加死鎖的機率。除此之外,slave線程也是有無視檢查直接通行的權限;
不足:采用os_event_t管理入隊和出隊,雖可以防止饑餓等待,但管理開銷比較大,;
改進:采用busy polling投票獲取slot,沒獲取的則睡眠等待;可為了減輕排隊開銷,但有可能導致饑餓等待;
為此新引入參數
Innodb_adaptive_sleep_delay:布爾型,用於激活或關閉adaptive sleep delay
Innodb_adaptive_max_sleep_delay:以微秒為單位,定義最大睡眠delay
adaptive 的算法是:
如果sleep了當前值以後還是不能進入,就把sleep時間+1.
如果還有線程在sleep時,已經有了空閒線程,就把當前值的sleep 時間減半
innodb_thread_concurrency限制行的並發度,但是在提交階段innodb的結構和鎖爭用很嚴重的。MySQL從5.0就開始引進的innodb_commit_concurrency,這個參數設置了同一時刻允許同時commit的線程數。默認是0即不限制,取值范圍0-1000,不可動態修改。