mod_proxy+mod_perl+MySQLでProxy Error

2月末にDebianのaptitudeが言うまま全パッケージを更新して、Debian 5.xでサポート対象外となったApache 1.3+mod_perlを手作業でインストールした後、mod_perlで動かしているMovableTypeにmod_proxy経由でアクセスすると、時々

502 Proxy Error
Reason: Document contains no data
というエラーが発生するようになった。

しばらく放置した後に起こることから、mod_perl+MySQLでよく問題になる、時間が経つとMySQLへのコネクションが無効になってしまうために起こる、いわゆる"The morning bug"絡みだろうということはすぐに想像がついて、実際MySQLを再起動すると必ず起こったので、それだと確信した。
しかし、通常はmod_perlがDBD::mysqlを介してMySQLに接続すると、"auto_reconnect"の設定が自動的に有効になるので、この問題は起こらないはずである。
(参考:man DBD::mysqlの"mysql_auto_reconnect"の項)

if either the GATEWAY_INTERFACE or MOD_PERL envionment variable is set, DBD::mysql will turn mysql_auto_reconnect on
実際、DBD/mysql.pmでログ出力してみると、mysql_auto_reconnectの値は1になっていた。しかし、mysql.pmの先は.so形式のバイナリなので、実際に再接続が試されているかは調べられなかった。

ここで、"Proxy Error"は、たまたまこの環境で結果としてそうなるだけで、同じ問題に遭遇した人が皆それに行き当たる訳ではないことは落ち着いて考えると明白だったのだが、"mysql proxy error"で検索して情報を探したため、長期に渡って悩むことになってしまった。
それでも、mod_perl+MovableTypeの組み合わせにApache::DBIを加えてコネクション・プーリングすると何かが解決した、という情報を得て、これだ!と思ってApache::DBIをインストールして組み込んでみたが、解決しなかった。

Apache::DBIのドキュメントを読むと、DBDによってはtimeout時にpingメソッドがエラーを返すので、そういう時は自前のpingメソッドを書くと問題を回避できる、と書いてあった。

Most DBI drivers have a working ping() method, but if the driver you're using doesn't have one and the database handle is no longer valid, you will get an error when accessing the database. As a work-around you can try to add your own ping() method using any database command which is cheap and safe
これだ!と思ってDBD/mysql.pmにpingメソッドを加えてみたが、そもそもpingは呼ばれていなかった。

落ち着いてApacheのエラーログをよく見ると、

[notice] child pid 7987 exit signal Segmentation fault (11)
というのが出ていた。すぐさま、そういう時はPHPをコンパイルし直せという情報を見つけて、これだ!と思って作り直すべきPHPを探すと、どこにもインストールされていなかった。

その後の調べで、DBD::mysqlのv4.007で生じたバグであり、v4.006に戻すかv4.009以降に更新すると直るらしいことがわかった。

仕方なく、CPANを使ってDBD::mysqlをコンパイルしようとすると、mysql_configが無い、というエラーが出た。Debian 5.xではmysql_configはlibmysqlclient15-devというパッケージをインストールしないと使えないらしい。これはわかりづらい。

結局、CPANでDBD::mysqlのv4.010をインストールすることによって、うちの"Proxy Error"は解消した。


モヤモヤが解けてすっきりしたのだが、不毛感が拭い去れない。
果たしてこれから同じ問題に出くわす人はいるのだろうか。DebianのDBD::mysqlがバージョンアップされたらもう誰も遭遇しないだろうし、前からDebianでDBD::mysqlを長時間動かしていた人はみな既に何らかの方法で対処しているだろう。
…とは思うのだが、一応書き記すことにした。