H2 数据库定期损坏

H2 database corruption on a regular basis

我是 an open-source application 专为自托管而设计的开发者。因此,许多人在各种系统、操作系统和硬件上使用它。它使用 Kotlin 和 Spring Boot 构建,并使用 H2 作为数据库。我遇到的问题是许多用户时常面临数据库损坏(我也发生过几次)。

损坏总是以下形式:

org.h2.jdbc.JdbcSQLNonTransientException: General error: "java.lang.IllegalStateException: Chunk 20221 not found [1.4.200/9]" [50000-200]

我无法查明这些损坏的任何特定原因。该应用程序不使用任何危险的 H2 选项。我在网络或 Whosebug 上找不到任何与我(恕我直言)平凡使用 H2 相关的内容。


我正在使用:

连接字符串非常简单:

jdbc:h2:~/.komga/database.h2

应用程序偶尔会进行大量写入(在文件系统扫描期间),但之后它主要进行读取。


您对如何更好地配置 H2 以避免这些问题有什么建议吗?

  1. 如果您的应用程序将 Thread.interrupt() 用于调用嵌入式数据库的线程,这就是损坏的原因,请不要这样做或使用 async: 文件系统(jdbc:h2:async:…).

  2. 如果带有H2的类加载器可以被强制卸载(例如在某些应用服务器上)或者应用程序将以某种异常方式终止,您需要在它之前关闭所有连接或执行SHUTDOWN 命令并等待其完成。

  3. 如果您尝试使用某些旧版本的 H2 打开数据库文件,它可能会损坏由较新版本创建的文件。

  4. 您可能 运行 遇到 H2 中的一些错误,因此如果您可以构建一个独立的测试用例 (Java / JDBC / SQL只有,没有第三方库),你需要在 GitHub 上填写一个新问题。您也可以尝试从其当前源构建 H2,存储后端有一些变化,但当前 H2 在其他方面与 1.4.200 有很大不同,您使用的第三方库可能尚未准备好使用它。

  5. 您可以使用旧版 PageStore 后端而不是默认后端,方法是在创建数据库时将 ;MV_STORE=FALSE 附加到 JDBC URL。此后端使用 table 级别的锁(您需要在所有事务中以相同的顺序锁定 table )并且不会并行执行来自不同会话的命令,但它更可靠。

  6. 可以使用单独的H2 Server进程;这种配置通常比嵌入式数据库更可靠,但速度较慢。

  7. 无论如何,对于任何 DBMS,您都应该定期创建备份副本。 H2 具有用于此目的的 BACKUP 命令。