永久的資料庫連接是指在您的腳本結束執行時不關閉的 SQL 連接。當收到一個永久連接的請求時。PHP 將檢查是否已經存在一個(前面已經開啟的)相同的永久連接。如果存在,將直接使用這個連接;如果不存在,則建立一個新的連接。所謂“相同”的連接是指用相同的用戶名和密碼到相同主機的連接。
註: 另外,還有一些其它的擴展庫也支援永久連接,例如 IMAP 擴展庫。
對 WEB 伺服器的工作和分布負載沒有完全理解的讀者可能會錯誤地理解永久連接的作用。特別的,永久連接不會在相同的 SQL 連接上為您提供建立“用戶會話”的能力,也不提供有效建立事務的能力。實際上,從嚴格意義上來講,永久連接不會給您提供任何非永久連接無法提供的特殊功能。
為什麼?
這和 WEB 伺服器工作的方式有關。您的 WEB 伺服器可以用三種方法來利用 PHP 產生 WEB 頁面。
第一種方法是將 PHP 用作一個“外殼”。以這種方法執行,PHP 會為向您的 WEB 伺服器提出的每個 PHP 頁面請求產生並結束一個 PHP 解釋器線程。由於該線程會隨每個請求的結束而結束,因此任何在這個線程中利用的任何資源(例如指向 SQL 資料庫伺服器的連接)都會隨線程的結束而關閉。在這種情況下,您使用永久連接不會獲得任何地改變──因為它們根本不是永久的。
第二,也是最常用的方法,是把 PHP 用作多過程 WEB 伺服器的一個模塊,這種方法目前只適用於 Apache。對於一個多過程的伺服器,其典型特征是有一個父過程和一組子過程協調執行,其中實際產生 WEB 頁面的是子過程。當客戶端向父過程提出請求時,該請求會被傳遞給還沒有被其它的客戶端請求占用的子過程。這也就是說當相同的客戶端第二次向伺服端提出請求時,它將有可能被一個不同的子過程來處理。在這種情況下,永久連接使得每個子過程需要做的只是利用上一個頁面請求時建立的連接。也就是說,當另一個頁面向 SQL 資料庫提出連接請求時,它可以使用處理該請求的子過程先前建立的連接。
最後一種方法是將 PHP 用作多線程 WEB 伺服器的一個插件。目前 PHP 4 已經支援 ISAPI、WSAPI 和 NSAPI(在 Windows 環境下),這些使得 PHP 可以被用作諸如 Netscape FastTrack (iPlanet)、Microsoft's Internet Information Server (IIS) 和 O'Reilly's WebSite Pro 等多線程 WEB 伺服器的插件。永久連接的行為和前面所描述的多過程模型在本質上是相同的。注意 PHP 3 不支援 SAPI。
如果永久連接並沒有任何附加的功能,那麼我們使用它有什麼好處?
答案非常簡單──效率。當客戶端對您的 SQL 伺服器的連接請求非常頻繁時,永久連接將更加高效。連接請求頻繁的標準取決於很多因素。例如,資料庫的種類,資料庫服務和 WEB 服務是否在同一台伺服器上,SQL 伺服器如何加載負載等。但我們至少知道,當連接請求很頻繁時,永久連接將顯著的提高效率。它使得每個子過程在其生命周期中只做一次連接操作,而非每次在處理一個頁面時都要向 SQL 伺服器提出連接請求。這也就是說,每個子過程將對伺服器建立各自獨立的永久連接。例如,如果您有 20 個不同的子過程執行某腳本建立了永久的 SQL 伺服器永久連接,那麼實際上您向該 SQL 伺服器建立了 20 個不同的永久連接,每個過程占有一個。
注意,如果永久連接的子過程數目超過了您設定的資料庫連接數限制,系統將會產生一些缺陷。如果您的資料庫的同時連接數限制為 16,而在繁忙會話的情況下,有 17 個線程試圖連接,那麼有一個線程將無法連接。如果這個時候,在您的腳本中出現了使得連接無法關閉的錯誤(例如無限循環),則該資料庫的 32 個連接將迅速的受到影響。請查閱您使用的資料庫的文檔,以獲取關於如何處理已放棄的及閒置的連接的方法。
| 警告 |
在使用永久連接時還有一些特別的問題需要注意。例如在永久連接中使用資料表鎖時,如果腳本不管什麼原因無法釋放該資料表鎖,其隨後使用相同連接的腳本將會被永久的阻塞,使得您需要重新啟動 httpd 服務或者資料庫服務。另外,在使用事務處理時,如果腳本在事務阻塞產生前結束,則該阻塞也會影響到使用相同連接的下一個腳本。不管在什麼情況下,您都可以通過使用 register_shutdown_function() 函式來註冊一個簡單的清理函式來打開資料表鎖,或者滾回事務。或者更好的處理方法,是不在使用資料表鎖或者事務處理的腳本中使用永久連接,這可以從根本上解決這個問題(當然您也可以在其它地方使用永久連接)。 |
以下是一點重要的總結。永久連接是為通常連接建立一對一的分布而設計的。這意味著您必須能夠保証在將永久連接替換為非永久連接時,您腳本的行為不會改變。使用永久連接將(非常)有可能改變您腳本的效率,但不改變其行為!
請參閱 fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(), imap_popen(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(), mysql_pconnect(), OCIPLogon(), odbc_pconnect(), Ora_pLogon(), pfsockopen(), pg_pconnect() 及 sybase_pconnect().