最近、H2というjavaで実装されてるデータベースに接するようになりました。
この前、とあるアプリ経由でアクセスしているH2のデータベースファイルをそのアプリからの利用を実質不能にしてしまい、それを回復できたときのメモです。
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Timeout trying to lock table "...
こんなエラーがでてアプリケーションが先にすすめなくなることを経験しました。アプリのH2はやや古く1.3です。
今回の自分の場合として、これを修復できたときにやったこと
- java -cp h2-1.3.*.jar org.h2.tools.Recover => これで.sqlファイルにデータがダンプされる
- java -cp h2-1.3.*.jar org.h2.tools.RunScript -url jdbc:h2:file:///[path-to-sql] -script .sql =>これでダンプから複製DBファイル作ってくれる。
- java -cp h2-1.3.*.jar org.h2.tools.Shell で複製したdbファイルを起動し、[SET LOCK_MODE 0]を投入。
Recover/RunScriptは多分定番で、とりあえず試してみたらそれだけではだめでした。おそらく結果的に同じDBを復元していたのだと思われます。
Recoverの出力の.sqlを眺めていたら
SET LOCK_MODE 1
という行を見つけたのでShellで LOCK_MODEに0をセットしてみました。そのDBファイルを使ったら復活しました。
こうなった原因:一度(sqllineという)別ツールでアクセスしたからです。*1
原理的にはRecover/RunScriptでうまく行くはず*2と考え.sqlファイルを眺めつつ思いつけたのはラッキー。*3
というかアクセスしただけで属性変わるというのはどうなのだろうか。read-onlyモードとかあると嬉しい。でもsqllineはjdbcによる汎用のSQLコマンドラインツールでH2に対して特別になにしたというわけでない、とは思う。
まぁ、不用意に直接アクセスしたのが敗因です。開発テスト用のDBでしたが、それでもちょっと余計な時間を消費してしまいました。
# 昨年末に自分の環境が変わり、それで接する機会が多いとか・着目したい(せざるをえない)カテゴリーも変わってきてます。scalaというjvmベースの言語に関わるようになりました。インターネット・ネットワーク系からは遠ざかってますが、そちらの興味はまだあります。。。