MySQL的Sleep進程占用大量連接解決方法
鏈接:http://hi.baidu.com/ratmin/item/eaab88ca9addd425a1b50a74
==========================================
第一部分為產生大量sleep進程的原理及對應解決方法
第二部分為設置wait_timeout值,有效減少sleep進程
==========================================
第一部分開始
1、通常來說,MySQL出現大量Sleep進程是因為采用的PHP的MySQL長鏈接數據庫方式,即使用了mysql_pconnect來打開鏈接數據庫,解決辦法就是使用“短”鏈接,即mysql_connect函數。
2、在使用mysql_connect短鏈接方式打開數據庫,每個頁面在打開數據庫后,執行SQL完成,當頁面腳本結束的時候,這個MySQL連接會自動關閉並且釋放內存。但仍然出現大量Sleep進程,可以看看網站是否存在以下幾個方面的問題。
A,硬盤上存在大量的靜態文件,或者WEB服務器負荷太重,在處理HTTP請求響應變得太慢,這樣也有可能導致出現大量Sleep進程,解決方法適當調整WEB服務參數和文件,一味的靜態或者緩存化網頁內容並不是靈丹妙葯。
B,在網頁腳本中,有些計算和應用可能非常耗時,比如在0秒的時候打開數據庫執行完一段SQL代碼后,網頁腳本隨即花了20秒鍾進行一段復雜的運算,或者是require了一個龐大的PHP文件(比如含有幾千個違規關鍵字的過濾函數),哪么這個時候在MySQL后台看到的進程中,這個20秒的過程MySQL並沒有做任何事情了,一直處於Sleep狀態,直到這個頁面執行完畢或者達到wait_timeout值(被強行關閉),優化網頁腳本,盡量讓程序快速運行,或者在執行這段耗時的運行過程中,執行mysql_close把當前MySQL鏈接強行關閉。
C,在采集站中,MySQL中大量的Sleep進程這類現象尤其明顯(比如很多網友問道DeDeCMS的MySQL中出現大量Sleep),因為大部的采集器頁面在運行過程中,事先打開了一個MySQL鏈接(可能是為了驗證用戶權限等),然后開始使用file_get_contents之類的操作去獲取一個遠程的網頁內容,如果這個遠程的站點訪問速度太慢,比如花了10秒時間才把網頁取回,哪么當前采集腳本程序就一直阻塞在這里,並且MySQL啥事也沒干,一直處於Sleep狀態。解決方法同上,在發出file_get_contents采集遠程網頁的時候,使用mysql_close強行關閉MySQL的連接,等采集完成在適當需要的時候再重新mysql_connect即可。
==========================================
第二部分開始
設置wait_timeout的值,有效減少sleep進程
如果你沒有修改過MySQL的配置,缺省情況下,wait_timeout的初始值是28800。
wait_timeout過大有弊端,其體現就是MySQL里大量的SLEEP進程無法及時釋放,拖累系統性能,不過也不能把這個值設置的過小,否則可能會遭遇到“MySQL has gone away”之類的問題(你可以在程序里時不時mysql_ping一下,以便服務器知道你還活着,重新計算wait_timeout時間),使用
mysql>show processlist; 用這個命令來查看當前mysql的進程情況,可以看出大量的sleep進程的時間是多少,大部分的都是10左右的,這時wait_timeout值就可以設置成8-10;
設置wait_timeout的方法有2個:
# vi /etc/my.cnf (在windows下是my.ini)
[mysqld]
wait_timeout=10
# /etc/init.d/mysql restart
這個方法設置后即使服務器以后重啟,設置照樣生效,不過這個方法會造成mysql服務重啟,無論如何都應該盡可能避免;
下面看看在MySQL命令行里通過SET來設置:
mysql> set global wait_timeout=10;
mysql> show global variables like 'wait_timeout';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| wait_timeout | 10 |
+----------------------------+-------+
這里一個容易把人搞蒙的地方是如果查詢時使用的是show variables的話,會發現設置好像並沒有生效,這是因為單純使用show variables的話就等同於使用的是show session variables,查詢的是會話變量,只有使用show global variables,查詢的才是全局變量。
網絡上很多人都抱怨說他們set global之后使用show variables查詢沒有發現改變,原因就在於混淆了會話變量和全局變量,如果僅僅想修改會話變量的話,可以使用類似set wait_timeout=10;或者set session wait_timeout=10;這樣的語法。
這個方法只是臨時性的,如果服務器重啟后,wait_timeout的值又會變成28800。