持続的データベース接続持続的データベース接続って何?持続的接続は、スクリプトの実行終了時にも閉じられないリンクです。 持続的接続が要求された時、 PHP は(前もってオープンされたままになっている) 同じ持続的接続が既にオープンされていないかどうかを確認します。 そして、存在する場合には、それを使用します。存在しない場合には、 そのリンクを作成します。'同じ'接続とは、同じホスト、同じユーザー名、 同じパスワード(利用可能な場合)でオープンされた接続のことを意味します。 特定の接続を要求する方法はありませんし、 既存の接続と新しい接続のどちらを取得できるかを保証する方法もありません。 (すべての接続が使用中の場合や、 リクエストが別の接続プールを持つ、 別のワーカーによって処理される場合があります) つまり、PHP の持続的接続が使えない場合があるということです。 たとえば以下の場合です:
持続的接続は、 持続的でない接続にできない機能は 全く 提供しません。 WebリクエストWebサーバーを PHP と統合し、Webページを生成させる方法はふたつあります: 最初は、CGI "ラッパー"としてPHPを使用する方法です。このように実行した場合、 PHP インタプリタのインスタンスは、Webサーバーに(PHPページに関する) ページがリクエストされる度に生成され、破棄されます。 リクエスト毎に破棄されるために、(SQLデータベースサーバーへのリンクのような) 必要な全てのリソースは破棄される際にクローズされます。この場合、 持続的接続を使用することから得るものは何もありません。 持続的接続は持続しないのです。 2番目は、最も一般的ですが、PHP を PHP-FPM か、 マルチプロセスWebサーバー(現在はApacheのみが含まれます)のモジュールとして実行する方法です。 マルチプロセスサーバーは、通常、 実際にWebページを送信する複数のプロセス(子)を管理するプロセス(親)を有しています。 リクエストがクライアントから来ると、 親プロセスは、 他のクライアントにすでに送信を行っていないクライアントの一つに渡します。 このため、 同じクライアントが2番目のリクエストをサーバーに送信した際に最初のではなく他の子プロセスにより送信が行われる可能性があります。 持続的接続がオープンされているとき、 SQL サービスにリクエストを行うそれぞれのページは、 SQL サーバーへの確立された接続を再利用することができます。
コマンドラインのプロセスコマンドラインから実行する PHP は、 スクリプトごとに新しいプロセスを使います。 持続的接続は、コマンドラインから実行するスクリプト間では共有されません。 よって、cron やコマンドからのような一時的なスクリプトから、 持続的接続を使ってもなんの役にも立ちません。 とはいっても、役に立つ場面はあるかもしれません。 たとえば、たくさんのリクエストや、 個別のタスクがそれぞれのデータベース接続を必要とする多数のタスクを処理する アプリケーションサーバーを書いている場合が挙げられます。 持続的接続をなぜ使うのか?持続的接続は、SQLサーバーへ接続するオーバーヘッドが大きい場合には有効です。 このオーバーヘッドが実際に大きいがどうかは様々な要因に依存します。 例えば、データベースの種類、 Webサーバーが動作するのと同じコンピューターで動作しているか、 SQLサーバーを動作させているマシンの負荷、等となります。 肝心なのは、接続のオーバーヘッドが高い場合、 持続的接続は著しく効果があるということです。 持続的接続は、 SQLサーバーへの接続を要求するページをリクエスト毎に処理する代わりに、 子プロセスが動作中の間一回しかサーバーへの接続を行わないようにします。 このことは、 持続的接続をオープンしたプロセス毎に、 サーバーへの持続的接続をオープンするということになります。 例えば、 20の異なった子プロセスがSQLサーバーへの持続的接続を行うスクリプトを実行した場合、 各子プロセス毎にSQLサーバーへの20の異なった接続が行われます。 ありうる欠点: 接続数の上限しかし、データベースへの接続数を制限して使用している場合に、 持続的な子プロセスの接続数がその数を超える場合は、 持続的接続には気をつけたほうが良い欠点がいくつかあります。 もしデータベースの同時接続数の制限が16だとして、 サーバーに多くのアクセスがあったため、 17個の子プロセスが接続しようとするとそのうちの一つは接続に失敗します。 もしスクリプトにコネクションをシャットダウンしないようなバグ(例えば無限ループ)があると、 16程度の同時接続しか許容しないデータベースはすぐにダメになってしまいます。 持続的接続は通常、特定の時点で開く接続数を増加させます。 これはアイドル状態のワーカーが、 以前処理したリクエスト用の接続を保持し続けるためです。 リクエストの急増に対応するために多数のワーカーが起動された場合、 それらのワーカーが開いた接続は、 ワーカーが終了するかデータベースサーバーが接続を閉じるまで残ります。 データベースサーバーが許可する最大接続数が、 Webリクエストワーカーの最大数(それに cronジョブや、 管理接続などのその他の使用分を加えた数)よりも大きいことを確認してください。 放棄された接続や、アイドル状態の接続(タイムアウト)の処理方法について、 データベースのドキュメントで確認してください。 タイムアウトを長く設定すると、 同時に開かれる持続的接続の数が大幅に増加する可能性があります。 ありうる欠点: 接続の状態管理一部のデータベース拡張モジュールは、 接続が再利用される際にクリーンアップを自動的に実行します。 このクリーンアップのタスクを、 アプリケーション開発者の裁量に委ねる拡張モジュールもあります。 選択したデータベース拡張モジュールとアプリケーション設計によっては、 スクリプト終了前に手動でのクリーンアップが必要になる場合があります。 接続を予期しない状態に陥らせる可能性のある変更には以下が含まれます:
クリーンアップが行われていない、 または閉じられていないテーブルロックやトランザクションは、 他のクエリが無限にブロックされる原因となるほか、 その後の接続の再利用によって予期しない変更が生じる可能性があります。 誤ったデータベースが選択されている場合、 その後の接続の再利用ではクエリが期待通りに実行できなくなります (スキーマが十分に類似している場合、 誤ったデータベース上でクエリが実行される可能性があります)。 一時テーブルがクリーンアップされない場合、 後続のリクエストでは同じテーブルを再作成できません。 クリーンアップは、クラスのデストラクタまたは register_shutdown_functionを使用して実装できます。 また、クリーンアップの機能を組み込んだ、 専用の接続プールプロキシの使用も検討するとよいでしょう。 おわりに既に述べた持続的接続の振る舞いと、あり得る欠点を考慮すると、 持続的接続を使う場合は、必ず慎重に検討を行うべきです。 持続的接続を使う場合は、 アプリケーションを追加で変更し、 データベースサーバーとWebサーバーおよび/またはPHP-FPMを慎重に設定すべきです。 サーバーへ接続するオーバーヘッドの原因を調査・修正する別の代替案 (例:データベースサーバーへのDNS逆引きの無効化)や、 専用の接続プールプロキシを検討してください。 高トラフィックのWeb APIについては、代替のランタイムや、 長時間実行可能なアプリケーションサーバーの使用を検討してください。 参考
|