【perlメモ】coreserverでcronでDBIを使ってSQLiteを弄るcgiを実行すると「database table is locked(1) at dbdimp.c line 398」になる件
coreserverでSQLiteを使ったcgiというかperlのスクリプトを1時間ごとに実行するようにしてみたのですが、cronから以下のようなメールが送られてきます。
DBI::db=HASH(0x83c5da0)->disconnect invalidates 1 active statement handle (either destroy statement handles or call finish on them before disconnecting) at /virtual/hoge/public_html/hoge/hoge.cgi line 357.
closing dbh with active statement handles
なんだか、DBIでエラーになっていうようなので色々調べてみます。
database table is locked(1) at dbdimp.c line 398
デバッグログを見てみると上の様なエラーを出力していました。テーブルがロックされているとか何とか。このフレーズで検索してみると「finishしてなかったらして」みたいな回答を見つけたのですが、finishはしっかりとしているし、ちょっと複雑なDBの操作をしているのでどこか間違えているのではないかと思って何度も見なおしてみましたが直りません。
$hst->finish;
PRIMARY KEY制約の無いテーブルだとUPDATEした時に発生する的な記事も見かけて、実際にアップデートしているテーブルがPRIMARY KEY制約の無いテーブルだったので、PRIMARY KEY制約を付けてみたのですが、ダメでした。
そもそも手動で動かすとエラー無しで動くので、coreserverのクーロンはシェル(.sh)から起動する決まりになっていて少し変なのでよほど変な規制があるのかと思いました。
DBIモジュールをローカルに入れました。
> perl -e ‘use DBI; print "$DBI::VERSION\n";’
1.601
現在のバージョンを調べてみると1.601の様です。
現在のcpanの最新バージョンは1.628の様です。
Tim Bunce / DBI – search.cpan.org
ローカルに最新版をインストールしました。モジュールをローカルにインストールする方法は以下の通り。
[perlメモ]モジュールをローカル(ユーザー領域)にインストールする – KUMA TYPE
cpanmを使う方法も有ります。make testが制限でkillされることがあるのでmake testをしないか、cpanmを使ったほうが良い場合もあると思います。
> perl -e ‘use DBI; print "$DBI::VERSION\n";’
1.628
そしてバージョンは1.628の最新版になっていました。
この時少し疑問に思ったのですが、use libしているわけでもないのにローカルにある新しいバージョンのモジュールにアクセスできているのが不思議でしたが。これが答えでした。
2013/09/03 17:05:01 661051:database table is locked(1) at dbdimp.c line 398
2013/09/03 18:05:01 DBI = 1.601
そして、再度チャレンジしてみるのですが、やはりエラー、モジュールのバージョンをログに出力してみると1.601になってしまっていました。
あれれー
手動で実行するとちゃんと1.628で動いていました。
use lib;でちゃんとモジュールの場所指定しているのに・・・とおもったのですが、use libだともうすこしピンポイントで場所を指定しないとだめなのかな?
ということは、他の何かでパスが通っているはずだと思ってENVを覗いてみます。
> env|grep PERL
PERL5LIB=/virtual/hoge/local/lib/perl5:/virtual/hoge/local/lib/perl5/site_perl:/virtual/hoge/local/lib/perl5/site_perl/5.8.8/mach
>
なるほど、PERL5LIB環境変数でモジュールへのパスが張られていました。
ということは、shellでは環境変数が効いていないということのようです。
#!/bin/sh
export PERL5LIB=/virtual/hoge/local/lib/perl5:/virtual/hoge/local/lib/perl5/site_perl:/virtual/hoge/local/lib/perl5/site_perl/5.8.8/mach
/usr/local/bin/perl /virtual/hoge/hoge.cgi 1> /dev/null
shellスクリプトを弄ってexportでPERL5LIBを設定してみました。
今度は大丈夫でした。
やはりDBIのバージョンが古いことが原因のようでした。
そしてuse libへの過信とPERL5LIB環境変数の存在を忘れていました。
に付いてはモジュールをローカルへインストールする記事でもふれているのに・・・。まあ、忘れる時は忘れちゃいますよね。大事なことでも。
そういうわけで、かなり長時間ハマった問題が解決しました。
#そもそも、coreserverのcronの設定は設定後1時間後に反映されるとか表示されるので、そうそういじれないわけです。なおかつ、最低1時間間隔で実行しなくてはいけないので、設定はいじれないし、実行は1時間毎だしでなかなか結果を見ることが出来なくて解決に手間取りました。手動で動いてcronだとエラーになるというところで気づけばよかったんですけどね。coreserverのcronがおかしな仕様だと思い込んでいたので目が曇ってました。
そういうわけで、これを記しておきます。
やっぱり自由にいじれるVPSがいいな~。最初の設定が面倒なのでなかなか重い腰が上がりませんけど。
タグ : cgi, CORESERVER, perl, SQLite