2010年1月7日木曜日

php と static 変数 とスレッド

ふと、次のような php のコードを見て、激しく不安を覚えた


static $db;

if( !isset($db) ) {
$db = &new FooDatabase;

if( $db->is_connected() ) {
... 接続処理
}
}



 どこに気持ち悪さがあるか?というと、データベースへの接続は、スレッド|プロセス毎に接続するのが普通だからである。これを解き明かすには、apache2 と php の実装を理解していないと、どうにもならない。

 apache2 では、prefork, thread, event の3タイプがあるようで、一般的な構成は prefork である。
なるほど、それならば、上記コードでも問題は無さそうである。HTTP/1.1 で Keep-Alive が効いている間はセッション毎に static $db を利用しているので継続性がある。Kepp-Alive でも一時的にTCPのセッションが切断されれば、!isset($db) が true となるぐらいである。
 event については、よくわからないのでパスするとして、thread では、大問題となる。そもそも、スレッド毎に接続しなければならないのに、php の static 変数は、プロセスが保有する領域である。これに対処するには、TLS(スレッド・ローカル・ストレージ)が必要になる。もしくは、mutex で保護されたグローバル・リソース・マネージャのようなものが必要になると思う。

 ここで大いに疑問を感じるのだが、大規模サイトでは Apache2 の構成を thread にしてるんじゃないか?と思うのだが、データベースの接続は、リクエスト毎にでもしてるんですか?うーん・・・ php は小規模向きか・・・。。

0 件のコメント: