web-dev-qa-db-ja.com

h2でテーブルをロックしようとしてタイムアウトエラーが発生しました

特定のシナリオで次のエラーが表示されます

別のスレッドがバルクアップロード操作を介して多くのユーザーに入力されており、別のWebページですべてのユーザーのリストを表示しようとしていました。リストクエリは、次のタイムアウトエラーをスローします。このタイムアウトエラーを回避できるように、このタイムアウトを設定する方法はありますか。

Env:h2(最新)、Hibernate 3.3.x

Caused by: org.h2.jdbc.JdbcSQLException: Timeout trying to lock table "USER"; SQL statement:

[50200-144]

    at org.h2.message.DbException.getJdbcSQLException(DbException.Java:327)
    at org.h2.message.DbException.get(DbException.Java:167)
    at org.h2.message.DbException.get(DbException.Java:144)
    at org.h2.table.RegularTable.doLock(RegularTable.Java:482)
    at org.h2.table.RegularTable.lock(RegularTable.Java:416)
    at org.h2.table.TableFilter.lock(TableFilter.Java:139)
    at org.h2.command.dml.Select.queryWithoutCache(Select.Java:571)
    at org.h2.command.dml.Query.query(Query.Java:257)
    at org.h2.command.dml.Query.query(Query.Java:227)
    at org.h2.command.CommandContainer.query(CommandContainer.Java:78)
    at org.h2.command.Command.executeQuery(Command.Java:132)
    at org.h2.server.TcpServerThread.process(TcpServerThread.Java:278)
    at org.h2.server.TcpServerThread.run(TcpServerThread.Java:137)
    at Java.lang.Thread.run(Thread.Java:619)
    at org.h2.engine.SessionRemote.done(SessionRemote.Java:543)
    at org.h2.command.CommandRemote.executeQuery(CommandRemote.Java:152)
    at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.Java:96)
    at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.Java:342)
    at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.Java:208)
    at org.hibernate.loader.Loader.getResultSet(Loader.Java:1808)
    at org.hibernate.loader.Loader.doQuery(Loader.Java:697)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.Java:259)
    at org.hibernate.loader.Loader.doList(Loader.Java:2228)
    ... 125 more
45
user339108

はい、 ロックタイムアウトを変更できます 。デフォルトは比較的低く、1秒(1000ミリ秒)です。

多くの場合、問題は別の接続がテーブルをロックしていることであり、複数バージョンの同時実行を使用すると問題も解決します(;MVCC=trueをデータベースURLに)。

45
Thomas Mueller

私はまったく同じ問題に直面し、パラメーター「MVCC = true」を使用して解決しました。このパラメーターの詳細については、H2のドキュメントをご覧ください: http://www.h2database.com/html/advanced.html#mvcc

39
Bruno ARLIGUY

このエラーが発生する場合は、おそらく、バルクデータベース操作でトランザクションを使用しないでくださいをお勧めします。代わりに、個々の更新ごとにトランザクションを実行することを検討してください。一括インポート全体をトランザクションとして考えるのは理にかなっていますか?おそらくない。もしそうなら、はい、MVCC = trueまたはより大きなロックタイムアウトが妥当な解決策です。

ただし、ほとんどの場合、非常に長いトランザクションを実行しようとしているため、このエラーが表示されていると思います。つまり、本当に長いトランザクションを実行していることに気付いていません。これは確かに私自身のケースであり、レコードの書き込み方法(トランザクションを使用しないか、より小さいトランザクションを使用する)に注意を払うだけで、ロックタイムアウトの問題は解決しました。

5
Tom Carchrae

統合テストでこの問題がある場合(つまり、サーバーがh2 dbにアクセスし、統合テストがサーバーを呼び出す前にdbにアクセスしてテストを準備する)、テストの前に実行されるスクリプトに「コミット」を追加して、データはサーバーを呼び出す前にデータベースにあります(MVCC = trueなし-デフォルトで有効になっていない場合、これは少し奇妙です)。

5
unludo

DBUnit、H2、およびHibernateの操作-同じエラー、MVCC = trueが役立ちましたが、データの削除後のテストではエラーが発生します。これらのケースを修正したのは、トランザクション内で実際の削除コードをラップすることでした:

Transaction tx = session.beginTransaction();
...delete stuff
tx.commit(); 
1
Boyko

PlayFrameworkでこの問題が発生しました

JPAQueryExceptionが発生しました:名前=?のmodels.Pageからクエリを実行中にエラーが発生しました:テーブル "PAGE"をロックしようとしてタイムアウトしました

私が持っていたので、それは並べ替えの無限ループで終わった

@前

関数がそれ自体を繰り返し呼び出す原因にならない限り

@Before(unless = "getUser")

1

接続文字列にMVCC = trueが含まれていましたが、上記のエラーが引き続き発生していました。 ;DEFAULT_LOCK_TIMEOUT=10000;LOCK_MODE=0を追加して問題が解決しました

0
Ev.Rei.