1. 程式人生 > >MySQL中sleep線程過多的處理方法

MySQL中sleep線程過多的處理方法

rec 連接超時 服務 一行 client out char* mysql連接 測試

先說具體方法:

先在MySQL中操作

set global wait_timeout = 60;
set global interactive_timeout = 60;


然後在配置文件裏修改(/etc/my.cnf):
[mysqld]
interactive_timeout = 120 #<==此參數設置後wait_timeout自動生效。
wait_timeout = 120

wait_timeout -- 指的是MySQL在關閉一個非交互的連接之前所要等待的秒數

interactive_time -- 指的是MySQL在關閉一個交互的連接之前所要等待的秒數(交互連接如mysql gui tool中的連接)

什麽是長連接?

其實長連接是相對於通常的短連接而說的,也就是長時間保持客戶端與服務端的連接狀態。

通常的短連接操作步驟是:

連接-》數據傳輸-》關閉連接

而長連接通常就是:

連接-》數據傳輸-》保持連接-》數據傳輸-》保持連接-》…………-》關閉連接

這就要求長連接在沒有數據通信時,定時發送數據包,以維持連接狀態,短連接在沒有數據傳輸時直接關閉就行了

什麽時候用長連接,短連接?

長連接主要用於在少數客戶端與服務端的頻繁通信,因為這時候如果用短連接頻繁通信常會發生Socket出錯,並且頻繁創建Socket連接也是對資源的浪費。

但是對於服務端來說,長連接也會耗費一定的資源,需要專門的線程(unix下可以用進程管理)來負責維護連接狀態。

總之,長連接和短連接的選擇要視情況而定。

首先,如果使用了長連接而長期沒有對數據庫進行任何操作,那麽在timeout值後,mysql server就會關閉此連接,而客戶端在執行查詢的時候就會得到一個類似於“MySQL server has gone away“這樣的錯誤。

在使用mysql_real_connect連接數據庫之後,再使用mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) 來設置為自動重連。這樣當mysql連接丟失的時候,使用mysql_ping能夠自動重連數據庫。如果是在mysql 5.1.6之前,那麽則應在每次執行完real_connect 之後執行mysql_options( &mysql, MYSQL_OPT_RECONNECT, … ) ,如果是mysql 5.1.6+,則在connect之前執行一次就夠了。

查看mysql連接數

mysqladmin -uroot -p processlist

實際的測試中我發現,當設置了MYSQL_OPT_RECONNECT為1時,超時後再查看processlist,則自動建立的連接不在列表中,但事實上連接確實建立並被使用了。

在MYSQL的默認設置中,如果一個數據庫連接超過8小時沒有使用(閑置8小時),服務器將斷開這條連接,後續在該連接上進行的查詢操作都將失敗。網絡上對該問題的描述非常多。也提供了相應的解決辦法。我在這裏提一些我自己的看法。

解決辦法一:修改MYSQL服務器的配置參數

道理非常簡單,MYSQL的默認設置是在數據庫連接超過8小時沒有使用後將其斷開,如果我們將這個時間改成更大的數值,那麽連接超時所需的時間就會更長,也就意味著更不容易超時。網絡上提供的修改方法一般是修改/etc/my.cnf,在這個文件中添加一行wait_timeout=你需要設置的超時時間 。實際上有一種比較簡單的方法來修改這個參數:

首先作為超級用戶登錄到MYSQL,註意必須是超級用戶,否則後面會提示沒有修改權限。然後輸入

show global variables like ‘wait_timeout‘;

回車執行後顯示目前的超時時間:

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| wait_timeout | 28800 |

+---------------+-------+

1 row in set (0.00 sec)

上面顯示的是默認的超時時間,即8個小時(單位是秒)。現在重新設置該參數,例如我們要將超時時間設置成10個小時,可以輸入:

set global wait_timeout=36000;

回車執行,顯示:

Query OK, 0 rows affected (0.00 sec)

表示設置成功,可以重新使用show global variables like ‘wait_timeout‘來驗證。

這種方法比較直觀,而且設置的參數立即生效。但如果/etc/my.cnf中沒有配置,則重啟服務後,global變量會從/etc/my.cnf中讀取新的變量值。

下邊是一段示例代碼:

if(!mysql_real_connect(&logdb, my_hostname, my_user, my_password, my_dbname, my_port, my_sock, 0)){
ast_log(LOG_ERROR, "Failed to connect to mysql database %s on %s.\n", my_dbname, my_hostname);
use_mysql = 0;
} else {
char value = 1;
mysql_options(&logdb, MYSQL_OPT_RECONNECT, (char*)&value);
use_mysql = 1;
}

wait_timeout和interactive_timeout總結

(1)interactive_timeout:
參數含義:服務器關閉交互式連接前等待活動的秒數。交互式客戶端定義為在mysql_real_connect()中使用CLIENT_INTERACTIVE選項的客戶端。
參數默認值:28800秒(8小時)

(2)wait_timeout:
參數含義:服務器關閉非交互連接之前等待活動的秒數。
在線程啟動時,根據全局wait_timeout值或全局interactive_timeout值初始化會話wait_timeout值,取決於客戶端類型(由mysql_real_connect()的連接選項CLIENT_INTERACTIVE定義)。

參數默認值:28800秒(8小時)

問題1:這裏為什麽要同時設置interactive_timeout,wait_timeout的設置才會生效?
答: 不設置interactive_timeout,wait_timeout也會生效。
問題2:interactive的值如果設置的和wait_timeout不同,為什麽Interactive_timeout會覆蓋wait_timeout?
答:在交互模式下(CLIENT_INTERACTIVE),interactive_timeout才生效,非交互模式下,不生效。

問題3:在進行MySQL優化時,因為interactive_timeout決定的是交互連接的時間長短,而wait_timeout決定的是非交互連接的時間長短。如果在進行連接配置時mysql_real_connect()最後一個參數client_flag不設置為CLIENT_INTERACTIVE,是不是interactive_timeout的值不會覆蓋wait_timeout?
答:可以做實驗試試。

問題4:為了減少長連接的數量,在設置優化時是不是可以將interactive_timeout的值設置的大些,而wait_timeout的值設置的小些?但是問題2的描述好像又不允許這樣。。。

答:如2所述,在交互模式下,interactive_timeout取代wait_timeout。這樣,如果有的客戶端是交互模式方式連接mysql server。那麽客戶端的timeout受制於interactive_timeout。如果有的客戶端是非交互模式,長連接mysql server。那麽客戶端的timeout受制於wait_timeout。(是否是交互模式的連接,由客戶端決定)

MySQL中sleep線程過多的處理方法