持続的接続を理解するために(その1)
とりあえず理解していることと理解していないことをメモ。
通常はブラウザからウェブサーバにアクセスがあった場合、アクセスごとに処理される。ページを連続して閲覧したとしても、それらは個々のアクセスとして処理される(連続した処理とみなすためには、別途処理を記述する必要がある)。これをふまえ、クライアントからのアクセスでオープンされたデータベースへのリンクコネクションは、通常そのスクリプト終了時に必ず(自動で)閉じられるが、持続的接続を使用すると、一連のスクリプトが終了しても、リンクコネクションは閉じられない(手動で閉じることは出来ない)。
持続的接続によるリンクコネクションが閉じられるタイミングについての記述が見つけられない。ふとマニュアルの設定項目に目を通したらいくつか関連しそうな記述を見つけた。
http://www.php.net/manual/ja/mysql.configuration.php
- mysql.allow_persistent
持続的接続を可能にするか否か 。 - mysql.max_persistent
プロセスごとの持続的MySQL接続の最大数 。
そもそも持続的接続ならプロセスで必要な接続は一つでいいのではないのか。
それともプロセスで複数の持続的接続(違うデータベースへの接続)をおこなうということなのか。 - mysql.max_links
プロセスごとの接続最大数。これは持続的接続に限った話ではない。 - mysql.connect_timeout
接続の有効時間。応答待ち時間と兼用。
調べれば調べるほどわからないことは増える。とりあえず接続時間(切断されるタイミング)という意味ではmysql.connect_timeoutという設定項目に関連性がありそうだけど、これってタイムアウト処理だから違うよね。
再度マニュアルに戻り「持続的データベース接続」の項を参照した。ここにapacheとの絡みの記述がある。
2番目は、最も一般的ですが、PHPをマルチプロセスWebサーバー(現在はApacheのみが含まれます)のモジュールとして実行する方法です。マルチプロセスサーバーは、通常、実際にWebページを送信する複数のプロセス(子)を管理するプロセス(親)を有しています。リクエストがクライアントから来ると、親プロセスは、他のクライアントにすでに送信を行っていないクライアントの一つに渡します。このため、同じクライアントが2番目のリクエストをサーバーに送信した際に最初のではなく他の子プロセスにより送信が行われる可能性があります。持続的接続がオープンされているとき、SQLサービスにリクエストを行うそれぞれのページはSQLサーバへの確立された接続を再利用することができます。
ブラウザからリクエストがあった場合、apacheのプロセス(親)は空いている子プロセスを使って応答する。だから連続したアクセスであっても、常に同じ子プロセスから応答がかえるわけではない、ということか。でもよくわからない。もう少し読み進むと・・・。
例えば、20の異なっ た子プロセスがSQLサーバーへの持続的接続を行うスクリプトを実行した場 合、各子プロセス毎にSQLサーバーへの20の異なった接続が行われます。
つまりapacheの子プロセスごとにデータベースへのリンクコネクションが張られるということか。これはapacheの子プロセスの最大数とmysql.max_persistentやmysql.max_linksの設定と密接に関係しそうだ(そういえば昔どこかでそういう記述を見た覚えがある)。
しかし、気をつけなければならないことが一つあります。それはデータベースへの接続数を制限して使用している場合に、持続的な子プロセスの接続数がその数を超えると問題が発生し得ることです。もしデータベースの同時接続数の制限が16だとして、サーバに多くのアクセスがあったため17個の子プロセスが接続しようとするとそのうちの一つは接続に失敗します。もしスクリプトにコネクションをシャットダウンしないようなバグ(例えば無限ループ)があると16程度の同時接続しか許容しないデータベースはすぐにダメになってしまいます。使用しているデータベースが、中断された、もしくは使用されていないコネクションをどのように扱うかを確認してみてください。
こういうことだ。今すぐにイメージできないけれど、図を描けばすぐに理解できそうだ。
このページで少し理解が進んだかもしれない。まずCGI版では動作しないということ。これは当たり前。CGI版では接続するたびにPHPのインスタンスが生成される(逆を言えば接続が終了するごとにインスタンスが破棄される)ので、持続のしようがない。マルチプロセスなウェブサーバ(apache)のモジュールや、マルチスレッドなウェブサーバ(IISなど)のプラグインとして動作する場合に限り、持続する。
ということでapacheの子プロセスの生存期間を調べてみるのがよさそう。