gotson
gotson

Reputation: 3907

H2 database corruption on a regular basis

i'm the developper of an open-source application designed for self-hosting. As such, it is used by many people on various systems, OSes, and hardware. It's built using Kotlin and Spring Boot, and uses H2 as the database. The problem i have is that many users are facing database corruption from times to times (it happened to me also a few times).

The corruptions are always of the form:

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

I can't pinpoint any particular reason for those corruptions. The application doesn't use any dangerous H2 options. I couldn't find anything on the web or Stackoverflow that relates to my (imho) mundane use of H2.


I'm using:

The connection string is pretty straightforward:

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

The application is doing heavy writes once in a while (during file system scanning), but afterwards it's doing mostly reads.


Would you have suggestions on how to better configure H2 to avoid those issues ?

Upvotes: 2

Views: 3671

Answers (1)

Evgenij Ryazanov
Evgenij Ryazanov

Reputation: 8188

  1. If your application uses Thread.interrupt() for threads doing calls into embedded database, this is the reason of corruption, don't do this or use the async: filesystem (jdbc:h2:async:…).

  2. If classloader with H2 can be forcibly unloaded (on some application servers, for example) or application is going to be terminated in some abnormal way, you need to close all connections before it or execute the SHUTDOWN command and wait for its completion.

  3. If you try to open the database file with some older version of H2, it can corrupt the file created by a more recent version.

  4. You may run into some bug in H2, so if you can build a standalone test case (Java / JDBC / SQL only, no third-party libraries), you need to fill a new issue on GitHub. You can also try to build H2 from its current sources, there were some changes in the storage backend, but current H2 is very different from 1.4.200 in other aspects and third-partly libraries that you use may be not yet ready to work with it.

  5. You can use the legacy PageStore backend instead of default one by appending ;MV_STORE=FALSE to the JDBC URL when you create your database. This backend uses table-level locks (you need to lock tables in the same order in all your transactions) and doesn't execute commands from different sessions in parallel, but it is more reliable.

  6. You can use a separate H2 Server process; such configuration is usually more reliable than embedded databases, but it works slower.

  7. In any case, with any DBMS, you should create backup copies on regular basis. H2 has BACKUP command for this purpose.

Upvotes: 2

Related Questions