尝试在h2中locking表的超时错误

在某些情况下,我得到以下错误

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

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 

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

在很多情况下,问题是另一个连接已经locking了表,并且使用多版本并发也解决了这个问题(append ;MVCC=true )。

我遇到了相同的问题,并使用参数“MVCC = true”,它解决了它。 您可以在这里的H2文档中find关于此参数的更多解释: http : //www.h2database.com/html/advanced.html#mvcc

我想build议,如果你得到这个错误,那么也许你不应该在你的批量数据库操作上使用一个事务 。 考虑改为对每个更新进行一次交易:将整个批量导入视为一个事务是否合理? 可能不会。 如果是的话,是的,MVCC = true或更大的locking超时是一个合理的解决scheme。

不过,我认为在大多数情况下,您会看到这个错误,因为您正在尝试执行非常长的事务 – 换句话说,您并不知道您正在执行一个非常长的事务。 对于我自己来说,情况确实如此,我只是更加在意自己如何写logging(不使用事务或使用更小的事务),并且locking超时问题已得到解决。

对于那些有集成testing(即服务器正在访问h2数据库和集成testing正在访问数据库在调用服务器之前,准备testing)的问题(在testing之前执行的脚本添加一个“提交”确保在调用服务器之前数据在数据库中(没有MVCC = true – 如果默认情况下没有启用,我觉得有点“奇怪”)。

我在PlayFramework中遇到了这个问题

JPAQueryException发生:从models.Page执行查询时出错名称=?:超时尝试locking表“PAGE”

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

@之前

没有一个除非导致函数重复调用自己

@Before(除非= “的getUser”)

使用DBUnit,H2和Hibernate – 同样的错误,MVCC = true帮助,但是我仍然会在删除数据后进行任何testing。 什么修复这些案件是在一个交易中包装实际的删除代码:

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