持続的データベース接続

持続的接続は、スクリプトの実行終了時にも閉じられないリンクです。 持続的接続が要求された時、PHPは(前もってオープンされたままになって いる)同じ持続的接続が既にオープンされていないかどうかを確認します。 そして、存在する場合には、それを使用します。存在しない場合には、そ のリンクを作成します。'同じ'接続とは、同じホスト、同じユーザー名、 同じパスワード(利用可能な場合)でオープンされた接続のことを意味しま す。

Webサーバーの動作及び負荷の分散に関して熟知していない人は、持続的接 続において何が行われないかに関してミスを犯す可能性があります。特に、 持続的接続は、同じリンクで'ユーザーセッション'をオープンする機能 やトランザクションを効率的に確立する機能やその他のあらゆる機能を提 供しません。つまり、言いたいことを極めて簡単に述べると、持続的接続 は非持続的接続で使用できない いかなる 機能も提 供しません。

なぜ?

これは、Webサーバーの動作により行われるべきものです。Webページを生 成するためにPHPを利用するWebサーバーには、3種類の方法があります。

最初は、CGI "ラッパー"としてPHPを使用する方法です。このように実行し た場合、PHPインタプリタのインスタンスは、Webサーバーに(PHPページに 関する)ページがリクエストされる度に生成され、破棄されます。リクエス ト毎に破棄されるために、(SQLデータベースサーバーへのリンクのような) 必要な全てのリソースは破棄される際にクローズされます。この場合、持 続的接続を使用することから得るものは何もありません。持続的接続は持 続しないのです。

2番目は、最も一般的ですが、PHPをマルチプロセスWebサーバー(現在は Apacheのみが含まれます)のモジュールとして実行する方法です。マルチプ ロセスサーバーは、通常、実際にWebページを送信する複数のプロセス(子) を管理するプロセス(親)を有しています。リクエストがクライアントから 来ると、親プロセスは、他のクライアントにすでに送信を行っていないク ライアントの一つに渡します。このため、同じクライアントが2番目のリク エストをサーバーに送信した際に最初のではなく他の子プロセスにより送 信が行われる可能性があります。 持続的接続がオープンされているとき、SQL サービスにリクエストを行う それぞれのページは SQL サーバーへの確立された接続を再利用することが できます。

最後の方法は、PHPをマルチスレッドWebサーバーのプラグインとして使用する 方法です。現在、PHP 4 は、ISAPI, WSAPI, NSAPI を(Windows上で)サポー トしており、Netscape FastTrack、Microsoftの Internet Information Server (IIS)、O'Reillyの WebSite Proのようなマルチスレッド型サーバー のプラグインとしてPHPを使用することが可能です。この場合の動作は前記 のマルチプロセス型モデルと同様です。

持続的接続が機能を全く付加しないとしたら、優れている点はなんでしょう?

答えはかなり簡単です。効率です。持続的接続は、SQLサーバーへ接続する オーバーヘッドが大きい場合には有効です。このオーバーヘッドが実際に 大きいがどうかは様々な要因に依存します。例えば、データベースの種類、 Webサーバーが動作するのと同じコンピューターで動作しているか、SQLサー バーを動作させているマシンの負荷、等となります。肝心なのは、接続の オーバーヘッドが高い場合、持続的接続は著しいということです。持続的 接続は、SQLサーバーへの接続を要求するページをリクエスト毎に処理する 代わりに子プロセスが動作中の間一回しかサーバーへの接続を行わないよ うにします。このことは、持続的接続をオープンしたプロセス毎にサーバー への持続的接続をオープンするということになります。例えば、20の異なっ た子プロセスがSQLサーバーへの持続的接続を行うスクリプトを実行した場 合、各子プロセス毎にSQLサーバーへの20の異なった接続が行われます。

しかし、気をつけなければならないことが一つあります。それはデータ ベースへの接続数を制限して使用している場合に、持続的な子プロセスの 接続数がその数を超えると問題が発生し得ることです。もしデータベース の同時接続数の制限が16だとして、サーバーに多くのアクセスがあったため 17個の子プロセスが接続しようとするとそのうちの一つは接続に失敗しま す。もしスクリプトにコネクションをシャットダウンしないようなバグ( 例えば無限ループ)があると16程度の同時接続しか許容しないデータベース はすぐにダメになってしまいます。使用しているデータベースが、中断さ れた、もしくは使用されていないコネクションをどのように扱うかを確認 してみてください。

警告

持続的接続を使用する際にはまだいくつか心に留めておく必要がある注意 点があります。一つは持続的接続でテーブルをロックする場合にスクリプト が何らかの理由でロックを外し損ねると、それ以降に実行されるスクリプト がその接続を使用すると永久にブロックしつづけてしまい、ウェブサーバーか データベースサーバーを再起動しなければならなくなるということです。もう 一つはトランザクションを使用している場合に、トランザクションブロック が終了する前にスクリプトが終了してしまうと、そのブロックは次に同じ接 続を使用して実行されるスクリプトに引き継がれる、ということです。 どちらの場合でも register_shutdown_function()を使用してテーブルの ロックを解除したりトランザクションをロールバックする簡単なクリーン アップ関数を登録することができます。しかしそれよりも良い方法は、テー ブルロックやトランザクションを使用するスクリプトでは持続的接続を使用 せず、問題を完全に避けて通ることです(他の箇所で使用する分には問題あ りません)。

重要なことをまとめます。持続的接続は、標準的な接続に1対1の割りつけ を行うように設計されています。このことは、常に 持続的接続を非持続的接続で置きかえ、かつ動作を変更しないということ ができることを意味します。持続的接続は、スクリプトの効率を変える かもしれません(おそらく変えます)が、動作は変更しません!

fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(), mysql_pconnect(), ociplogon(), odbc_pconnect(), oci_pconnect(), pfsockopen(), pg_pconnect(), sybase_pconnect()も参照してください。