尝试在h2中锁定表时出现超时错误

时间:2010-11-12 07:42:37

标签: h2

在某种情况下我收到以下错误

当一个不同的线程通过批量上传操作填充了很多用户时,我试图查看不同网页上所有用户的列表。列表查询会引发以下超时错误。有没有办法设置此超时,以便我可以避免此超时错误。

环境: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

8 个答案:

答案 0 :(得分:44)

是的,you can change the lock timeout。默认值相对较低:1秒(1000毫秒)。

在许多情况下,问题是另一个连接已锁定表,并且使用多版本并发也解决了问题(将;MVCC=true附加到数据库URL)。

答案 1 :(得分:39)

我遇到了同样的问题并且使用参数“MVCC = true”,它解决了它。您可以在H2文档中找到有关此参数的更多说明:http://www.h2database.com/html/advanced.html#mvcc

答案 2 :(得分:5)

对于那些遇到集成测试问题的人(即服务器访问h2 db并且集成测试在调用服务器之前访问db,准备测试),在测试之前执行的脚本中添加'commit'在调用服务器之前确保数据在数据库中(没有MVCC = true - 如果默认情况下没有启用它,我觉得有点'怪异')。

答案 3 :(得分:5)

我想建议如果您收到此错误,那么也许您不应该在批量数据库操作中使用事务。考虑在每次更新时进行交易:将整个批量导入视为交易是否有意义?可能不是。如果是,则是,MVCC = true或更大的锁定超时是合理的解决方案。

但是,我认为在大多数情况下,您会看到此错误,因为您正在尝试执行一个非常长的事务 - 换句话说,您不知道您正在执行一个非常长的事务。对我来说当然就是这种情况,我只是更加关注我如何编写记录(使用无事务或使用较小的事务)并解决了锁定超时问题。

答案 4 :(得分:1)

我在PlayFramework

中遇到了这个问题
  

发生JPAQueryException:执行查询时出错   models.Page where name =?:超时试图锁定表“PAGE”

它结束了无数循环,因为我有一个

  

@Before

没有导致该功能重复调用的除非

  

@Before(除非= “的getUser”)

答案 5 :(得分:1)

使用DBUnit,H2和Hibernate - 同样的错误,MVCC = true有帮助,但在删除数据后,我仍然会收到任何测试的错误。修复这些案例的原因是将实际删除代码包装在事务中:

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

答案 6 :(得分:0)

我的连接字符串中具有MVCC = true,但上面仍然出现错误。我添加了;DEFAULT_LOCK_TIMEOUT=10000;LOCK_MODE=0,问题就解决了

答案 7 :(得分:0)

从2020年用户处查看reference

参考文献基本上说:

设置当前会话的锁定超时(以毫秒为单位)。此设置的默认值为1000(一秒)。

此命令不会提交事务,并且回滚不会影响它。可以将此设置附加到数据库URL:jdbc:h2:./test;LOCK_TIMEOUT=10000