48

在特定情况下出现以下错误

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

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

8 回答 8

50

的,您可以更改锁定超时。默认值相对较低:1 秒(1000 毫秒)。

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

编辑:MVCC=true不再支持参数,因为从h2 1.4.200开始,对于默认引擎 MVStore 引擎来说总是如此。

于 2010-11-12T08:09:10.470 回答
39

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

于 2011-06-15T11:44:42.287 回答
6

对于那些在集成测试中遇到这个问题的人(即服务器正在访问 h2 db,并且集成测试在调用服务器之前访问 db 以准备测试),在测试之前执行的脚本中添加一个“提交”以确保在调用服务器之前数据在数据库中(没有 MVCC=true - 如果默认情况下未启用,我发现它有点“奇怪”)。

于 2011-11-07T14:25:39.283 回答
6

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

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

于 2012-10-28T17:09:17.640 回答
1

我在 PlayFramework 上遇到了这个问题

发生 JPAQueryException:从模型执行查询时出错。名称 = 的页面:超时尝试锁定表“PAGE”

它结束了各种各样的无限循环,因为我有一个

@前

没有除非导致函数重复调用自身

@Before(除非="getUser")

于 2011-09-18T22:30:22.957 回答
1

使用 DBUnit、H2 和 Hibernate - 同样的错误,MVCC=true 有帮助,但我仍然会在删除数据后的任何测试中遇到错误。解决这些情况的方法是将实际删除代码包装在事务中:

Transaction tx = session.beginTransaction();
...delete stuff
tx.commit(); 
于 2015-05-21T19:13:28.957 回答
1

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

于 2018-10-06T14:20:20.553 回答
0

来自 2020 年的用户,请参阅参考资料

基本上,参考资料说:

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

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

于 2020-05-27T02:30:12.810 回答