Oracle Instant Client 10.2.0.1を利用した場合、突然DBへ接続ができなくなる現象
【追記】(2008/02/13)
以下の対応を行ったのですが、また同様の現象が発生してしまいました。Oracle Instant Client 10.2.0.3にバージョンアップすることで問題が解消されていればよいのですが...
※このエントリへのアクセスがあるようなので、タイトルをもう少し分かりやすく変更しました。
以下のOSおよびソフトウェア組み合わせで動かしているウェブサーバがあります。
- Red Hat Enterprise Linux WS v.3
- Apache2.0.x (prefork)
- PHP4.4.x
- Oracle Instant Client 10.2.0.1
突然何の前触れもなくOracleへ接続ができなくなりました。Apacheのエラーログを見ると、以下のようなエラーが頻発していました。
[Sun Oct 01 02:00:12 2006] [error] [client xxx.xx.xxx.xxx] PHP Fatal error: Maximum execution time of 30 seconds exceeded in /xxx/xxx/xxx/xxx.php on line 31 [Sun Oct 01 02:00:12 2006] [error] [client xxx.xx.xxx.xxx] PHP Warning: Unknown(): OCI8 Recursive call!\n in Unknown on line 0
様子を見ていたのですが、接続先のDBサーバの負荷が高いわけでもなく、一向に収束する気配もないので、いったんApacheを再起動することにしました。本来であれば、以下のような形で起動するのですが、子プロセスが起動しない。
[root@xxx xxx]# ps auxf (snip) root 5091 0.0 0.8 98556 8884 ? S 15:50 0:00 /usr/local/httpd2.0.59/bin/httpd -k start nobody 5092 0.2 1.3 102756 13484 ? S 15:50 0:03 \_ /usr/local/httpd2.0.59/bin/httpd -k start nobody 5095 0.2 1.3 102748 13432 ? S 15:50 0:02 \_ /usr/local/httpd2.0.59/bin/httpd -k start nobody 5096 0.2 1.4 102756 14952 ? S 15:50 0:03 \_ /usr/local/httpd2.0.59/bin/httpd -k start nobody 5097 0.2 1.4 102748 14924 ? S 15:50 0:02 \_ /usr/local/httpd2.0.59/bin/httpd -k start nobody 5098 0.2 1.3 102756 13480 ? S 15:50 0:03 \_ /usr/local/httpd2.0.59/bin/httpd -k start nobody 5101 0.1 1.3 102748 13480 ? S 15:50 0:02 \_ /usr/local/httpd2.0.59/bin/httpd -k start (snip)
具体的には、以下のような感じで親プロセスしか起動せず、しかもCPUが100%近くのままになってしまいました。
[root@xxx xxx]# ps auxf (snip) root 5091 99.9 0.8 98556 8884 ? S 15:50 0:00 /usr/local/httpd2.0.59/bin/httpd -k start
しかもたちの悪いことに apachectl stop とコマンドを叩いても、not runningなんて怒られる始末。(起動してもhttpd.pidファイルも生成しないし、ログファイルも出力しないので正しく起動していないのでしょう)
問題がなんとも掴めないので、問題の切り分けをすることにしました。
まずはhttpd.confの設定を元の状態に戻して、Apacheが問題なく起動するか確認をしました。これは問題なく起動しました。次にデフォルトからphpの設定(LoadModuleとかAddTypeの辺り)を削除して起動しました。これも問題なく起動しました。最後にphpの設定を追記した状態で起動しました。すると先ほどのダメな状態に逆戻りしてしまいました。
上記からphp周りの設定に問題がある可能性があるので、php.iniの設定をデフォルトに戻すことにしました。まずはphp.iniをデフォルトに戻した上で、httpd.confにphpの設定を追記した状態でApacheを起動しました。すると今度はきちんと起動しました。php.iniは特別な設定をしているのは以下の個所だけなので、oci8.soのロードが怪しいのかなとあたりを付けました。
; Oracle extension=oci8.so
最近は設定を触っていないので、怪しいと言えば怪しい部分です。そこまではたどり着いたのですが、それ以上は何も分からずじまい。何せエラーログが吐き出されないのだからどうしようもないです。
別の切り口からということで、Apacheの親プロセスについてシステムコールとシグナルをトレースしてみると、何かヒントが得られるかもしれないと思い、調べてみました。すると以下の結果が得られました。
[root@xxx xxx]# strace -p 5091 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277
上記の「time(NULL)」をキーワードにして、Googleで検索をしてみるも、それらしきキーワードが見つからず、どうしようもない状態に。どうしようもないので、1人はそのまま原因調査をもう1人(というか俺ですが)が別の方法での対応を検討することにしました。
色々調べてもらった結果、別のキーワードを見つけて、原因と対応策が見つかりました。やったー!
[root@xxx xxx]# strace -f /usr/local/httpd2.0.59/bin/apachectl start access("/xxx/oracle/admin/network/conf/sqlnet.ora", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/oracle/10.2.0.1/client/network/admin/sqlnet.ora", F_OK) = -1 ENOENT (No such file or directory) access("/xxx/oracle/admin/network/conf/sqlnet.ora", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/oracle/10.2.0.1/client/network/admin/sqlnet.ora", F_OK) = -1 ENOENT (No such file or directory) fcntl64(161185400, F_SETFD, FD_CLOEXEC) = -1 EBADF (Bad file descriptor) fcntl64(161185416, F_SETFD, FD_CLOEXEC) = -1 EBADF (Bad file descriptor) times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 times(NULL) = -2141161277 (snip)
ってことでやっと本質の部分に触れるわけですが、どうやらOracle Instant Client 10.2.0.1をインストールし、利用しているサーバを連続248日以上稼動させると発生するバグのようです。
Back in the days of Oracle 8, there was a fairly imfamous bug in the Oracle client where new connections would fail if the client had been up for 248 days or more. This got fixed, and wasn't a problem with Oracle 9i at all. Now Oracle have managed to introduce a similar bug in 10.2.0.1, although in my experience the number of days appears to be shorter (180+).
うーん、結局Oracleのバグが減員だったとは....この手のバグは結構有名だったりするのでしょうか?
ちなみに以下のサイトで詳しい情報が載っていますので、参考にして下さい。
- SQL*Plus 10.2.0.1.0 does not work on ...
- Oracle 10.2.0.1 Instant Client hanging?
- Re: Oracle10g issue - times() call fails
ってことで、結論として対応は以下の通りになりました。
これで無事に問題は解消されました。はぁー、疲れた。
【追記】
Oracle Instant Clientは、oracle.comからダウンロードして下さい。oracle.comのアカウント登録が必要です*1。
oracle.co.jpでは最新版のOracle Instant Clientが用意されていませんので注意が必要です。いつになったら最新版を用意してくれるんでしょうかね。古いバージョンだと問題が起こるのだから、置き換えてもらわないと困るのですが。
【2007/03/24追記】
Oracle Instant Clientの最新版(Linux x86の場合、10.2.0.3)がOTN Japanにて公開されています。
追記を書きました。
*1:OTNのアカウントとは異なるので注意して下さい