1. 程式人生 > >mysql 併發執行緒引數innodb_thread_concurrency

mysql 併發執行緒引數innodb_thread_concurrency

一、thread_concurrency

首先,最重要的一點,這個引數已經在最新版本的MySQL中被移除了,官方最新5.7版本的doc上面對thread_concurrency有這樣的說明:

thread_concurrency變數是針對於Solaris 8及低版本的系統,設定了這個變數MySQL會呼叫thr_setconcurrency()函式。這個函式允許應用程式給同一時間執行的執行緒系統提示所需數量的執行緒。當前的Solaris版本中這個引數已經沒有作用了,這個引數在MySQL 5.6.1中已經被標記為過時,在5.7.2版本的MySQL中被移除。

二、innodb_thread_concurrency引數介紹

MySQL的兩種儲存引擎:MyISAM和InnoDB,InnoDB支援事務,也是MySQL預設的儲存引擎,在InnoDB中,我們可以通過設定引數innodb_thread_concurrency限制執行緒的數量。

先來看一下官方Configuring Thread Concurrency for InnoDB對innodb_thread_concurrency引數的配置說明,翻譯如下:

InnoDB使用作業系統執行緒來處理使用者的事務請求。(在事務提交或回滾之前可能給InnoDB引擎帶來很多的請求)。在現代化作業系統和多核處理器的伺服器上,上下文切換是非常高效的,大多數工作負載執行沒有任何併發執行緒數量的限制。在MySQL 5.5及以上版本中,MySQL做了可伸縮性的改進,它減少了這種在InnoDB內部限制併發執行執行緒數量的需要。

它有助於在最小化的情況下進行執行緒之間的上下文切換,InnoDB可以使用各種技術來限制作業系統併發執行執行緒的數量(因此大批量的請求可以在任何一個時間得到處理)。當InnoDB從使用者會話收到一個新的請求,如果執行緒併發執行的數量達到預定義的限制,那麼新的請求會先睡眠一段時間後再次嘗試。在睡眠後不能按計劃執行的請求會被放入先入/先出佇列,並最終處理。但那些等待獲取鎖的執行緒則不會被計入到併發執行執行緒的數量中。 我們可以通過設定配置引數innodb_thread_concurrency來限制併發執行緒的數量,一旦執行執行緒的數量達到這個限制,額外的執行緒在被放置到對佇列中之前,會睡眠數微秒,可以通過設定引數innodb_thread_sleep_delay來配置睡眠時間。

在MySQL 5.6.3之前的版本中,MySQL要求通過測試和實驗找到innodb_thread_sleep_delay的最優值,這個最優值可能會因工作負載情況不同而發生改變。在MySQL 5.6.3及更高版本中,你可以通過設定引數innodb_adaptive_max_sleep_delay為innodb_thread_sleep_delay設定最大允許的值,InnoDB會根據當前執行緒排程活動自動調整innodb_thread_sleep_delay的值,這種動態調整機制有助於工作的執行緒,在系統負載低時或系統接近滿負荷運轉時,都能夠順利的排程。

在MySQL和InnoDB之前的版本系列中,innodb_thread_concurrency的預設值,以及其隱含的限制併發執行緒執行的數量都進行過調整。在當前最新版本的MySQL中,innodb_thread_concurrency的預設值為0,它表示預設情況下不限制執行緒併發執行的數量。

另外,InnoDB只有當併發執行緒數量有限時,執行緒才會休眠。當執行緒數量沒有限制時,所有這些都同樣被安排。也就是說,如果innodb_thread_concurrency是0,值 innodb_thread_sleep_delay被忽略。

當執行緒數量有限時(當innodb_thread_concurrency>0時),InnoDB通過允許在執行單個SQL語句期間進行的多個請求進入InnoDB而不需要遵守設定的限制 ,從而減少上下文切換開銷innodb_thread_concurrency。由於SQL語句(例如join)可能包含多個行操作,所以InnoDB分配指定數量的 “ tickets ”,允許以最少的開銷重複排列執行緒。

當一個新的SQL語句開始,當前執行緒沒有“tickets”時,它就必須遵守innodb_thread_concurrency引數設定,一旦這個執行緒有權進入InnoDB,它會被分配一個“tickets”,它可以通過這個“tickets”用於隨後進入InnoDB執行行操作,如果“tickets”使用完畢,該執行緒將會被驅逐,innodb_thread_concurrency引數會被放回到先入/先出佇列中等待的執行緒等待再次觀察。一旦這個執行緒再次有權進入InnoDB,“tickets”又會被重新分配,我們可以通過設定全域性引數innodb_concurrency_tickets來指定“tickets”的數量,預設情況下是5000。正在等待獲取鎖的執行緒,一旦鎖可用,會被立即分配一個“tickets”。

這些引數的正確值取決於當前系統環境和負載情況。嘗試各種不同的值,以確定哪些值適用於當前應用程式。在限制併發執行的執行緒數之前,在多核及多處理器的計算機上,檢查一下InnoDB的配置引數是否可以改善效能,比如innodb_adaptive_hash_index。

三、innodb_thread_concurrency&innodb_thread_sleep_delay&innodb_concurrency_tickets

這三個引數的配合使用就是這樣的一個故事(看網上一個哥們寫的,摘抄下來)

一個屋子內有一個頭牌妓女叫Innodb, 大家都想接近她.

老鴇(MySQL)不可能允許那麼多人同時進屋去,就限制每次只能進去幾個(上下和手嘛..),這個限制的名字就叫(innodb_thread_concurrency).

其他的人怎麼辦,只能在外面排成長隊依次進入.同時老鴇說,大爺你們可以睡一會,這樣就不用苦苦等待了.

這裡老鴇就會個一段時間(innodb_thread_sleep_delay)叫醒一位大爺,以免睡不醒了.

老鴇也怕總是叫醒大爺不好交代,就看快到了再叫,老鴇自己發明了一個自適應的叫醒演算法,能夠儘量減少喚醒次數.

但是大爺會規定一個最長喚醒時間,就是必須在這樣的時間(innodb_adaptive_max_sleep_delay)時喚醒我.

如此當有人從內部出來以後,等待的大爺(排在最前面的)就可以進入享受魚水之歡了.

但是每位大爺能夠支援的時間不一樣,有的一分鐘(quicker),有的大爺需要幾個小時.這樣外面等待的大爺就會有意見,哎呀,怎麼還不出來.

老鴇又想了一個辦法,規定每個人不能在姑娘房裡呆10分鐘以上(innodb_concurrency_tickets), 有特別持久的人就需要在10分鐘時出來,在繼續排隊(排在隊尾).

等到下一次輪到他再進行魚水之歡.

人物對應:老鴇(MySQL), 大爺(threads), 姑娘(innodb)

如何優化innodb_concurrency_tickets,那就得看哪位大爺重要,比如宰相的兒子在這裡等,那宰相的兒子又十分持久,最好就用多點時間(增大innodb_concurrency_tickets)

如果宰相的兒子不持久,那就用小時間快點排到他。

四、innodb_thread_concurrency使用建議

在官方文件上,對於innodb_thread_concurrency的使用,也給出了一些建議,如下:

如果一個工作負載中,併發使用者執行緒的數量小於64,建議設定innodb_thread_concurrency=0;

如果工作負載一直較為嚴重甚至偶爾達到頂峰,建議先設定innodb_thread_concurrency=128,並通過不斷的降低這個引數,96, 80, 64等等,直到發現能夠提供最佳效能的執行緒數,例如,假設系統通常有40到50個使用者,但定期的數量增加至60,70,甚至200。你會發現,效能在80個併發使用者設定時表現穩定,如果高於這個數,效能反而下降。在這種情況下,建議設定innodb_thread_concurrency引數為80,以避免影響效能。

如果你不希望InnoDB使用的虛擬CPU數量比使用者執行緒使用的虛擬CPU更多(比如20個虛擬CPU),建議通過設定innodb_thread_concurrency引數為這個值(也可能更低,這取決於效能體現),如果你的目標是將MySQL與其他應用隔離,你可以考慮繫結mysqld程序到專有的虛擬CPU。但是需要注意的是,這種繫結,在myslqd程序一直不是很忙的情況下,可能會導致非最優的硬體使用率。在這種情況下,你可能會設定mysqld程序繫結的虛擬CPU,允許其他應用程式使用虛擬CPU的一部分或全部。

在某些情況下,最佳的innodb_thread_concurrency引數設定可以比虛擬CPU的數量小。定期檢測和分析系統,負載量、使用者數或者工作環境的改變可能都需要對innodb_thread_concurrency引數的設定進行調整

轉自:http://www.ywnds.com/?p=9821