當需要使用PHP連接MySQL數據庫的時候,會發現有兩種數據庫連接函數:mysql_connect()和mysql_pconnect()。
1、mysql_connect()
在腳本開始的時候,mysql_connect()會創建一個新的連接,腳本結束的時候就會關閉連接。腳本每一次執行,它都會創建一個新的連接。
2、mysql_pconnect()
當使用mysql_pconnect()連接數據庫時,它首先會判斷是否已經存在了數據庫連接,如果存在,就會利用先用的資源ID,反之,就會創建一個新的連接。
在創建連接之後,函數返回資源ID(如果有)。當腳本再次調用的時候,它並不會創建新的連接。當然,腳本結束的時候,也不會關閉連接。這稱之為持久連接。
但是,使用mysql_pconnect()時,需要對服務器配置做一下微調,譬如限制連接數,超時連接,以及處理空連接等。
3、怎麼使用這兩個函數
如果你的應用有很大流量,應該使用mysql_pconnect()函數,反之考慮mysql_connect()函數。
如果PHP和MySQL在同一台服務器上或者在本地網絡,連接次數是可以忽略的,因為無論在哪種情況之下,持久連接都沒有優勢可言。
4、使用mysql_pconnect()應該留意的事
一般來說,當你鎖定一個表時,連接關閉之後是就自動解鎖了。但由於持久連接不關閉,任何你不小心鎖定的表仍然會保持鎖定的狀態,唯一解鎖的辦法就是等待連接超時或者手動殺死進程。在進行事物處理時也會造成這個問題。
同樣,臨時表在連接關閉之後也會被刪除。但由於持久連接不關閉,臨時表就不再是臨時表了。如果你完成需求後不刪除臨時表,它將作為一個新的客戶端連接,並且是對於同一個連接。在設置Session變量的時候,會造成同樣的問題。
在Apache上使用持久連接的效果並不會很好。當Apache收到客戶端的一個請求時,會打開一個新的數據庫連接,而不是利用已經存在持久連接去打開數據庫,這將導致很多空閒進程、浪費資源,當達到最大連接數時,還是造成未知錯誤。
假設mysql服務器被配置為最大支持10個並發. 而apache被配置為使用100個子進程.
apache由一個父進程來協調將收到的http request分發給哪個空閒中的子進程處理, 這樣很快處理了10個http請求, 假設10個都分配給了不同的子進程, 那末10條跟mysql間的持久連接就建立了, mysql的能力已經到了極限.
這時又來了一個http請求, apache將它分給其他的任意不在這10個子進程中的進程, 那末這個進程就沒有辦法建立到mysql的連接了, 因為坑位已經滿了.
使用持久連接還會有其他方面的問題.
如果在你腳本中使用了持久連接, 又進行了鎖表操作的話, 如果到腳本結束也沒有去解鎖的話. 那麼下次再運行這個腳本的話, 它為了獲得lock table會在那裡無盡地等待過去的它unlock table, 過去的它已經不能回來了, 這裡成了個死循環. 除非重啟web或者mysql服務器. 另一個會造成鎖定的就是事務了.
apache模塊方式下:
區別在於當php以apache模塊方式運行時, 由於apache有使用進程池, 一個httpd進程結束後會被放回進程池, 這也就使得用pconnect打開的的那個mysql連接資源不被釋放, 於是有下一個連接請求時就可以被復用.
這就使得在apache並發訪問量不大的時候, 由於使用了pconnect, php節省了反復連接db的時間, 使得訪問速度加快. 這應該是比較好理解的.
但是在apache並發訪問量大的時候, 如果使用pconnect, 會由於之前的一些httpd進程占用的mysql連接沒有close, 則可能會因為mysql已經達到最大連接著, 使得之後的一些請求永遠得不到滿足.
例如:
若mysql最大連接數設為500, 而apache的最大同時訪問數設為2000
假設所有訪問都會要求訪問db, 而且操作時間會比較長
當前500個請求的httpd都沒有結束的時候...之後的httd進程都是無法連接到mysql的(因已經達到mysql最大連接數). 只有當前500個httpd進程結束或被復用才可以連接得到了mysql.
其實這個也很好解釋了xgy_p的測試中若操作比較簡單, pconnect比connect效率高很多, 而且跟使用jsp的連接池的速度比較接近. 因為這個時候httpd進程可以不斷的給復用.
而 當DB操作復雜, 耗時較長時, 因httpd會fork很多並發進程處理, 而先產生的httpd進程不釋放db連接, 使得後產生的httpd進程無法連上db. 因為這樣沒有復用其它httpd進程的mysql連接. 於是會就產生很多連接超時, 像一開始的1000個並發連接測試說幾乎都是連接超時就是這個原因.
---
(反進來看jsp用的如果是純粹的db連接池, 則不會有因為達到mysql連接上限而連不上的問題, 因為jsp的連接池會使得可以等待其它連接使用完畢並復用. )
因此在並發訪問量不高時,使用pconnect可以簡單提高訪問速度, 但在並發量增大後, 是否再使用pconnect就要看程序員的選擇了..
就我個人認為, php現在對mysql的連接並沒有真正用到連接池, pconnect也只是相當於借了apache的進程池來用, 所以在並發訪問量大的時候pconnect並不能很好的提高訪問DB效率. 在這一點上. php的確比不上jsp