java - h2数据库无法处理中断如何处理

标签 java database h2

如何处理 h2 数据库无法处理中断的问题,我偶尔会发现我的嵌入式 h2 数据库似乎已损坏,特别是我修改了 ExecutorService,以便如果任务花费太长时间,就会取消该任务。该任务将被取消,但随后的数据库访问会失败,并出现以下异常:

23/07/2019 14.23.31:BST:DeleteDuplicatesController:start:SEVERE: commit failed
org.hibernate.TransactionException: commit failed
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:187)
    at com.jthink.songkong.db.ReportCache.save(ReportCache.java:46)
    at com.jthink.songkong.reports.AbstractReport.setReportDatabaseObject(AbstractReport.java:365)
    at com.jthink.songkong.reports.DeleteDuplicatesReport.setReportDatabaseObject(DeleteDuplicatesReport.java:333)
    at com.jthink.songkong.reports.DeleteDuplicatesReport.closeReport(DeleteDuplicatesReport.java:377)
    at com.jthink.songkong.analyse.toplevelanalyzer.DeleteDuplicatesController.deleteAnyDups(DeleteDuplicatesController.java:606)
    at com.jthink.songkong.analyse.toplevelanalyzer.DeleteDuplicatesController.start(DeleteDuplicatesController.java:665)
    at com.jthink.songkong.ui.swingworker.DeleteDuplicates.doInBackground(DeleteDuplicates.java:43)
    at com.jthink.songkong.ui.swingworker.DeleteDuplicates.doInBackground(DeleteDuplicates.java:20)
    at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at javax.swing.SwingWorker.run(SwingWorker.java:334)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.TransactionException: unable to commit against JDBC connection
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:116)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:180)
    ... 14 more
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.IllegalStateException: Reading from nio:C:/Users/Paul/AppData/Roaming/SongKong/Database/Database.mv.db failed; file length -1 read length 4096 at 1541494 [1.4.199/1]"; SQL statement:
COMMIT [50000-199]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:502)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:427)
    at org.h2.message.DbException.get(DbException.java:194)
    at org.h2.message.DbException.convert(DbException.java:347)
    at org.h2.command.Command.executeUpdate(Command.java:280)
    at org.h2.jdbc.JdbcConnection.commit(JdbcConnection.java:542)
    at com.mchange.v2.c3p0.impl.NewProxyConnection.commit(NewProxyConnection.java:1284)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doCommit(JdbcTransaction.java:112)
    ... 15 more
Caused by: java.lang.IllegalStateException: Reading from nio:C:/Users/Paul/AppData/Roaming/SongKong/Database/Database.mv.db failed; file length -1 read length 4096 at 1541494 [1.4.199/1]
    at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:883)
    at org.h2.mvstore.DataUtils.readFully(DataUtils.java:420)
    at org.h2.mvstore.FileStore.readFully(FileStore.java:98)
    at org.h2.mvstore.MVStore.readBufferForPage(MVStore.java:1048)
    at org.h2.mvstore.MVStore.readPage(MVStore.java:2186)
    at org.h2.mvstore.MVMap.readPage(MVMap.java:554)
    at org.h2.mvstore.Page$NonLeaf.getChildPage(Page.java:1086)
    at org.h2.mvstore.Page.get(Page.java:221)
    at org.h2.mvstore.MVMap.get(MVMap.java:402)
    at org.h2.mvstore.MVMap.get(MVMap.java:389)
    at org.h2.mvstore.MVStore.getMapName(MVStore.java:2737)
    at org.h2.mvstore.MVStore.renameMap(MVStore.java:2650)
    at org.h2.mvstore.tx.TransactionStore.commit(TransactionStore.java:453)
    at org.h2.mvstore.tx.Transaction.commit(Transaction.java:389)
    at org.h2.engine.Session.commit(Session.java:691)
    at org.h2.command.dml.TransactionCommand.update(TransactionCommand.java:46)
    at org.h2.command.CommandContainer.update(CommandContainer.java:133)
    at org.h2.command.Command.executeUpdate(Command.java:267)
    ... 18 more
Caused by: java.nio.channels.ClosedChannelException
    at sun.nio.ch.FileChannelImpl.ensureOpen(FileChannelImpl.java:110)
    at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:721)
    at org.h2.store.fs.FileNio.read(FilePathNio.java:74)
    at org.h2.mvstore.DataUtils.readFully(DataUtils.java:406)
    ... 34 more
23/07/2019 14.23.31:BST:Errors:addError:SEVERE: Adding Error:commit failed

I have since found this issue

基本上,如果在嵌入模式下使用 H2,并且它收到中断,则所有后续访问都会失败,直到线程池关闭并重新打开。在我给出的示例中,一个进程必须被取消,因为它似乎被卡住了,除了中断之外没有其他解决方案

我还有另一种情况,通常 Controller 线程本身不直接执行数据库工作,所以我很难理解为什么当发生中断时为什么会导致数据库错误,因为这是由 Controller 线程处理的。我现在已经解决的问题是,我使用具有固定大小的 BlockingQueue 的 ExecutorService (这样我们就不会在内存中建立一个大队列),但是如果队列已满,则新任务实际上由 Controller 线程执行(因为 CallerRunsPolicy),所以 Controller 线程毕竟可以调用数据库。

我将 H2 与 hibernate 结合使用,并且在这两种情况下,在中断后立即调用以下内容

   HibernateUtil.closeFactory();

似乎解决了这个问题,但是我想这意味着具有 hibernate session 的任何其他线程都将被破坏,但至少新打开的 session 会没问题。所以我对这个解决方法不是特别满意,还有其他想法吗?

使用 H2 作为服务器不是一个解决方案,因为 H2 的重点是应用程序中包含的嵌入式数据库。

最佳答案

虽然没有正确记录使用异步协议(protocol)允许中断连接而不破坏所有其他连接。

关于java - h2数据库无法处理中断如何处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57165588/

相关文章:

java - 使用java从mongodb集合中获取值

android - 在 Android 中存储和搜索大文本数据的最佳方式

java - PreparedStatement.executeUpdate() 不插入 sqlite 数据库

plugins - 尝试在H2数据库中创建表时出现Liquibase错误

java - 查询时仅显示第一行

java - 如何在 Intellij 中将 Kotlin 与 H2 和 SQLite 结合使用

java - 类型不匹配 : cannot convert from int to boolean in while loop

java - 从网页获取 JSON 响应

mysql - sql查询使用join从2个表中检索数据

java - 在H2中使用 'FILE_LOCK=NO'安全吗?