數據庫持久連線
持久的數據庫連線是指在指令碼結束執行時不關閉的連線。當收到一個持久連線的請求時。PHP 將檢查是否已經存在一個(前面已經開啟的)相同的持久連線。如果存在,將直接使用這個連線;如果不存在,則建立一個新的連線。所謂「相同」的連線是指用相同的使用者名稱和密碼到相同主機的連線。
對 web 伺服器的工作和分佈負載沒有完全理解的讀者可能會錯誤地理解持久連線的作用。特別的,持久連線不會在相同的連線上提供建立「使用者會話」的能力,也不提供有效建立事務的能力。實際上,從嚴格意義上來講,持久連線不會提供任何非持久連線無法提供的特殊功能。
為什麼?
這和 web 伺服器工作的方式有關。web 伺服器可以用三種方法來利用 PHP 產生 web 頁面。
第一種方法是將 PHP 用作一個單獨執行的語言直譯器(CGI Wapper)。以這種方法執行,PHP 會為向 web 伺服器提出的每個 PHP 頁面請求產生並結束一個 PHP直譯器執行緒。由於該執行緒會隨每個請求的結束而結束,因此任何在這個執行緒中利用的任何資源(例如指向SQL 數據庫伺服器的連線)都會隨執行緒的結束而關閉。在這種情況下,使用持久連線和非持久連線沒有任何區別——因為PHP指令碼本身的執行不是持久的。
第二,也是最常用的方法,是把 PHP 用作多程序 web 伺服器的一個模組,這種方法目前只適用於 Apache。對於一個多程序的伺服器,其典型特徵是有一個父程序和一組子程序協調執行,其中實際產生 web 頁面的是子程序。每當客戶端向父程序提出請求時,該請求會被傳遞給還沒有被其它的客戶端請求佔用的子程序。這也就是說當相同的客戶端第二次向服務端提出請求時,它將有可能被一個不同的子程序來處理。在開啟了一個持久連線后,所有請求 SQL 服務的後繼頁面都能夠重用這個已經建立的 SQL Server 連線。
最後一種方法是將 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。
如果持久連線並沒有任何附加的功能,那麼使用它有什麼好處?
答案非常簡單——效率。當Web Server建立到SQL伺服器的連線耗費(Overhead)較高(如耗時較久,消耗臨時記憶體較多)時,持久連線將更加高效。Overhead高低取決於很多因素。例如,數據庫的種類,數據庫服務和web 服務是否在同一臺伺服器上,SQL 伺服器負載狀況等。當Overhead較高,每次建立數據庫連線成本較高時,持久連線將顯著的提高效率。它使得每個子程序在其生命週期中只做一次連線操作,而非每次在處理一個頁面時都要向SQL 伺服器提出連線請求。這也就是說,每個子程序將對伺服器建立各自獨立的持久連線。例如,如果有 20 個不同的子程序執行某指令碼建立了持久的 SQL 伺服器持久連線,那麼實際上向該 SQL 伺服器建立了 20 個不同的持久連線,每個程序佔有一個。
注意,如果持久連線的子程序數目超過了設定的數據庫連線數限制,系統將會產生一些問題。如果數據庫的同時連線數限制為 16,而在繁忙會話的情況下,有 17 個執行緒試圖連線,那麼有一個執行緒將無法連線。如果這個時候,在指令碼中出現了使得連線無法關閉的錯誤(例如無限循環),則該數據庫的 16 個連線將迅速地受到影響。請查閱使用的數據庫的文件,以獲取關於如何處理已放棄的及閑置的連線的方法。
在使用持久連線時還有一些特別的問題需要注意。例如在持久連線中使用數據表鎖時,如果指令碼不管什麼原因無法釋放該數據表鎖,其隨後使用相同連線的指令碼將會被持久的阻塞,使得需要重新啟動 httpd 服務或者數據庫服務。另外,在使用事務處理時,如果指令碼在事務阻塞產生前結束,則該阻塞也會影響到使用相同連線的下一個指令碼。不管在什麼情況下,都可以通過使用 register_shutdown_function() 函式來註冊一個簡單的清理函式來打開數據表鎖,或者回滾事務。或者更好的處理方法,是不在使用數據表鎖或者事務處理的指令碼中使用持久連線,這可以從根本上解決這個問題(當然還可以在其它地方使用持久連線)。
以下是一點重要的總結。持久連線與常規的非持久連線應該是可以互相替換的。即將持久連線替換為非持久連線時,你的指令碼的行為不應該發生改變。使用持久連線只應該改變指令碼的效率,不應該改變其行為!
參見 fbsql_pconnect(),ibase_pconnect(),ifx_pconnect(),ingres_pconnect(),msql_pconnect(),mssql_pconnect(),mysql_pconnect(),ociplogon(),odbc_pconnect(),ora_plogon(),pfsockopen(),pg_pconnect() 和 sybase_pconnect()。