表“SYS”中的并发更新:插入多个记录时h2数据库失败

时间:2018-04-02 14:07:03

标签: java database h2

我在下面遇到了h2数据库1.4.197的错误。基本上,我正在尝试在处理后立即更新记录。

我不使用insert,而是使用merge语句,因为我不想要重复记录。以下是我的询问:

merge into tableName key(col1,col2) values(?,?,?);

我正在使用最大连接池设置为100的连接池,并且从调试开始,我发现错误是随机顺序引发的。话虽如此,当插入第1000条记录时,首先抛出错误。在第二次执行时,它发生了第554条记录。

这是我的连接字符串:

jdbc:h2:file:" + DB_NAME + ";MV_STORE=true;MVCC=true;AUTO_SERVER=TRUE

下面是堆栈跟踪。

org.h2.jdbc.JdbcSQLException: General error: "java.lang.RuntimeException: Unexpected code path" [50000-197]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
    at org.h2.message.DbException.get(DbException.java:168)
    at org.h2.message.DbException.convert(DbException.java:307)
    at org.h2.message.DbException.toSQLException(DbException.java:280)
    at org.h2.message.TraceObject.logAndConvert(TraceObject.java:357)
    at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:268)
    at com.verscend.dxcg.reports.db.h2.QueryHelper.insertOrUpdateTable(QueryHelper.java:20)
    at com.verscend.dxcg.audit.AuditLogGenerator.process(AuditLogGenerator.java:22)
    at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:103)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.component.seda.SedaConsumer.sendToConsumers(SedaConsumer.java:298)
    at org.apache.camel.component.seda.SedaConsumer.doRun(SedaConsumer.java:207)
    at org.apache.camel.component.seda.SedaConsumer.run(SedaConsumer.java:154)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: Unexpected code path
    at org.h2.message.DbException.throwInternalError(DbException.java:254)
    at org.h2.message.DbException.throwInternalError(DbException.java:267)
    at org.h2.engine.Session.unlockAll(Session.java:985)
    at org.h2.engine.Session.endTransaction(Session.java:760)
    at org.h2.engine.Session.commit(Session.java:708)
    at org.h2.command.Command.stop(Command.java:157)
    at org.h2.command.CommandContainer.stop(CommandContainer.java:122)
    at org.h2.command.Command.executeUpdate(Command.java:296)
    at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:249)
    ... 23 more

org.h2.jdbc.JdbcSQLException: Concurrent update in table "SYS": another transaction has updated or deleted the same row [90131-197]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.table.RegularTable.removeRow(RegularTable.java:375)
    at org.h2.engine.Database.removeMeta(Database.java:985)
    at org.h2.engine.Database.updateMeta(Database.java:1698)
    at org.h2.command.ddl.Analyze.analyzeTable(Analyze.java:136)
    at org.h2.engine.Session.commit(Session.java:701)
    at org.h2.command.Command.stop(Command.java:157)
    at org.h2.command.CommandContainer.stop(CommandContainer.java:122)
    at org.h2.command.Command.executeUpdate(Command.java:296)
    at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:249)
    at com.verscend.dxcg.reports.db.h2.QueryHelper.insertOrUpdateTable(QueryHelper.java:20)
    at com.verscend.dxcg.audit.AuditLogGenerator.process(AuditLogGenerator.java:22)
    at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:103)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:198)
    at org.apache.camel.component.seda.SedaConsumer.sendToConsumers(SedaConsumer.java:298)
    at org.apache.camel.component.seda.SedaConsumer.doRun(SedaConsumer.java:207)
    at org.apache.camel.component.seda.SedaConsumer.run(SedaConsumer.java:154)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

` 我在这里失踪了什么?

1 个答案:

答案 0 :(得分:0)

我找到了解决此问题的临时方法:

如果在插入记录时引发异常(该异常仅每5-10.000条记录左右发生,看似随机发生),线程将等待10毫秒,然后重试以插入记录。如果重试也失败,则会向上传播异常,并且不会插入记录。

到目前为止,等待和重试似乎为数据库提供了足够的时间来解锁有问题的记录。