關於php應該在何時調用mysql_close()以及pconnect方式和傳統方式有何種區別收藏
以前我一直認為,當php的頁面執行結束時,會自動釋放掉一切。相信很多人都跟我想的一樣。但事實證明並不是這樣。比如session就不會隨着頁面執行完畢而釋放。
php的垃圾回收機制,其實只針對於php本身。對於mysql,php沒權利去自動去釋放它的東西。如果你在頁面執行完畢前不調用mysql_close(),那么mysql那邊是不會關閉這個連接的。如果你是用的是pconnect方式,即使你在頁面執行完畢前調用mysql_close(),也無法另mysql關閉這個連接。
也許在負載低的情況下,你感受不到有何不妥。下面我就來解釋這兩天我觀察出的現象:
在php中使用pconnect方式建立連接,然后到mysql客戶端下執行show processlist;如果你的負載到一定程度的話,你可以看到很多sleep的進程,這些進程就是人們常說的死連接,它們會一直保持sleep,直到my.cnf里面設置的wait_timeout這個參數值的時間到了,mysql才會自己殺死它。在殺死它的時候,mysql還會在error-log里面記錄一條Aborted connection xxx to db: 'xxx' user: 'xxx' host: 'xxx'的日志,用google翻譯一下,會得到一個相當強悍的解釋"胎死腹中的連接"!
那么造成sleep的原因,有三個,下面是mysql手冊給出的解釋:
1.客戶端程序在退出之前沒有調用mysql_close().
2.客戶端sleep的時間在wait_timeout或interactive_timeout規定的秒內沒有發出任何請求到服務器.
3.客戶端程序在結束之前向服務器發送了請求還沒得到返回結果就結束掉了.
上面是我根據google的翻譯改了下,可能有某些地方翻譯的不准確。原文請見下面:
1 The client program did not call mysql_close() before exiting.
2 The client had been sleeping more than wait_timeout or interactive_timeout seconds without issuing any requests to the server.
3 The client program ended abruptly in the middle of a data transfer
如果你的sleep進程數在同一時間內過多,再加上其他狀態的連接,總數超過了max_connection的值,那mysql除了root用戶外,就無法再繼續處理任何請求無法與任何請求建立連接或者直接down了。所以,這個問題在大負載的情況下還是相當嚴重的。如果發現你的mysql有很多死連接存在,首先要先檢查你的程序是否使用的是pconnect的方式,其次,檢查在頁面執行完畢前是否及時調用了mysql_close(),
還有一個辦法,你可以在my.cnf里面加上wait_timeout和interactive_timeout,把他們的值設的小一些,默認情況下wait_timeout的值是8小時的時間,你可以改成1個小時,或半個小時。這樣mysql會更快的殺死死連接。防止連接總數超過max_connection的值。或者把max_connection的值設置的更大,不過這樣顯然不妥,連接的數量越多,對你服務器的壓力越大。實際上那些連接都是冗余的,把它們盡快殺死才是上策。
以前總是說,在使用php連接mysql的時候,盡量不要使用pconnect的方式,看完我上面所說的那些,應該可以明白為什么了吧,因為我們使用php大多數情況下都是做web開發,web開發是面向多用戶,那么用戶的數量與mysql連接數是成正比的。使用pconnect的方式,即使你的調用mysql_close()也是無法釋放數據庫連接的,那么mysql中的死連接的數量就會越來越多了。
我認為,只有當你的應用屬於那種點對點方式,或者你能保證連接數量很少的情況,才有必要去采用pconnect的方式,因為連接數量少,那么讓它一直處於連接狀態,避免了重復打開關閉的過程。這樣可能會比傳統方式更好一些。
至於何時該去調用mysql_close(),最正確的做法是如果下面不再執行mysql的操作了,在你上一次執行完mysql操作后,立刻就調用mysql_close()。這才是最正確的做法,並不是總要把mysql_close()寫在頁面最后一行就可以了。
