H2数据库损坏恢复

0.前言

今天登录博客,发现首页报错,想着去后台重启下看看,发现服务器启动不起来了,报了一个如下的错误:

 1 org.h2.jdbc.JdbcSQLNonTransientConnectionException: File corrupted while reading record: null. Possible solution: use the recovery tool [90030-199]
 2     at org.h2.message.DbException.getJdbcSQLException(DbException.java:617) ~[h2-1.4.199.jar!/:na]
 3     at org.h2.message.DbException.getJdbcSQLException(DbException.java:427) ~[h2-1.4.199.jar!/:na]
 4     at org.h2.message.DbException.get(DbException.java:194) ~[h2-1.4.199.jar!/:na]
 5     at org.h2.mvstore.db.MVTableEngine$Store.convertIllegalStateException(MVTableEngine.java:205) ~[h2-1.4.199.jar!/:na]
 6     at org.h2.mvstore.db.MVTableEngine$Store.open(MVTableEngine.java:173) ~[h2-1.4.199.jar!/:na]
 7     at org.h2.mvstore.db.MVTableEngine.init(MVTableEngine.java:95) ~[h2-1.4.199.jar!/:na]
 8     at org.h2.engine.Database.getPageStore(Database.java:2739) ~[h2-1.4.199.jar!/:na]
 9     at org.h2.engine.Database.open(Database.java:769) ~[h2-1.4.199.jar!/:na]
10     at org.h2.engine.Database.openDatabase(Database.java:319) ~[h2-1.4.199.jar!/:na]
11     at org.h2.engine.Database.<init>(Database.java:313) ~[h2-1.4.199.jar!/:na]
12     at org.h2.engine.Engine.openSession(Engine.java:69) ~[h2-1.4.199.jar!/:na]
13     at org.h2.engine.Engine.openSession(Engine.java:201) ~[h2-1.4.199.jar!/:na]
14     at org.h2.engine.Engine.createSessionAndValidate(Engine.java:178) ~[h2-1.4.199.jar!/:na]
15     at org.h2.engine.Engine.createSession(Engine.java:161) ~[h2-1.4.199.jar!/:na]
16     at org.h2.engine.Engine.createSession(Engine.java:31) ~[h2-1.4.199.jar!/:na]
17     at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:336) ~[h2-1.4.199.jar!/:na]
18     at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:169) ~[h2-1.4.199.jar!/:na]
19     at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:148) ~[h2-1.4.199.jar!/:na]
20     at org.h2.Driver.connect(Driver.java:69) ~[h2-1.4.199.jar!/:na]
21 ......省略号......
22 Caused by: java.lang.IllegalStateException: File corrupted in chunk 1198302, expected page length 4..1024, got 976302644 [1.4.199/6]
23     at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:883) ~[h2-1.4.199.jar!/:na]
24     at org.h2.mvstore.MVStore.readBufferForPage(MVStore.java:1055) ~[h2-1.4.199.jar!/:na]
25     at org.h2.mvstore.MVStore.readPage(MVStore.java:2186) ~[h2-1.4.199.jar!/:na]
26     at org.h2.mvstore.MVMap.readPage(MVMap.java:554) ~[h2-1.4.199.jar!/:na]
27     at org.h2.mvstore.Page$NonLeaf.getChildPage(Page.java:1086) ~[h2-1.4.199.jar!/:na]
28     at org.h2.mvstore.Cursor.hasNext(Cursor.java:53) ~[h2-1.4.199.jar!/:na]
29     at org.h2.mvstore.MVStore.readStoreHeader(MVStore.java:793) ~[h2-1.4.199.jar!/:na]
30     at org.h2.mvstore.MVStore.<init>(MVStore.java:401) ~[h2-1.4.199.jar!/:na]
31     at org.h2.mvstore.MVStore$Builder.open(MVStore.java:3343) ~[h2-1.4.199.jar!/:na]
32     at org.h2.mvstore.db.MVTableEngine$Store.open(MVTableEngine.java:162) ~[h2-1.4.199.jar!/:na]
33     ... 139 common frames omitted

心想,坏了卧槽,数据库文件坏了。

1.找恢复工具

H2官方就提供恢复工具,地址:https://www.h2database.com/html/download-archive.html ,找到合适的版本,由于我的H2用的版本是1.4.199的版本,下载那个 Platform-Independent Zip 就行了,如下图:

 3.数据提取

  3.1解压下载好的ZIP到本地目录,如 h2Recover,自己记得就行,目录层级应该如下:

h2Recover
  - h2
      - bin
          - h2.bat
          - h2.sh
          - h2-1.4.199.jar
          - h2w.bat
      + src
      + docs
      + service
         build.bat
         build.sh

    我们需要的就是bin/h2-1.4.199.jar的这个文件

  3.2找到你损坏的数据库文件,以*.mv.db结尾的那个文件,复制到 bin 目录下

  3.3执行以下命令进行数据提取

java -cp h2-1.4.199.jar org.h2.tools.Recover

    jar包会自动找到当前目录下的db文件,然后生成对应的数据恢复脚本。

4.意外

  不出意外的话就要出现意外了,就知道没有这么的顺利,恢复工具报了一个和启动一样的错误:

 1 Exception in thread "main" java.lang.IllegalStateException: File corrupted in chunk 1198302, expected page length 4..1024, got 976302644 [1.4.199/6]
 2         at org.h2.mvstore.DataUtils.newIllegalStateException(DataUtils.java:883)
 3         at org.h2.mvstore.MVStore.readBufferForPage(MVStore.java:1055)
 4         at org.h2.mvstore.MVStore.readPage(MVStore.java:2186)
 5         at org.h2.mvstore.MVMap.readPage(MVMap.java:554)
 6         at org.h2.mvstore.Page$NonLeaf.getChildPage(Page.java:1086)
 7         at org.h2.mvstore.Cursor.hasNext(Cursor.java:53)
 8         at org.h2.mvstore.MVStore.readStoreHeader(MVStore.java:793)
 9         at org.h2.mvstore.MVStore.<init>(MVStore.java:401)
10         at org.h2.mvstore.MVStore$Builder.open(MVStore.java:3343)
11         at org.h2.mvstore.MVStoreTool.info(MVStoreTool.java:347)
12         at org.h2.tools.Recover.process(Recover.java:344)
13         at org.h2.tools.Recover.runTool(Recover.java:195)
14         at org.h2.tools.Recover.main(Recover.java:158)

5.上Google

  最后发现也有人在使用恢复工具的时候出现过同样的问题,甚至版本都一样的199,然后他发布了解决办法,详见 https://github.com/h2database/h2database/issues/2139

 

    有个小伙纸他说他提取数据时用的是 1.4.196 的版本,恢复时再换回的 1.4.199 的版本,互联网上有才的人和好人还是多的啊。

    遂在下了一个 1.4.196 的恢复工具,重新执行了第 3.3 步骤中的数据提取命令。居然可以了,会生成一个和你的库同名的 xx.h2.sql的文件,只是。。。。我一个平常备份也就是二三十M的DB文件,提取完成后的恢复脚本居然高达7个多G。先不管了,恢复数据看看先。。

6.数据还原

   原先被损坏的库先行备份、先行备份、先行备份,以免出错,然后执行以下命令,生成一个全新的数据库:

java -cp h2-1.4.199.jar org.h2.tools.RunScript -url jdbc:h2:./xxx -user username -password password -script xxx.h2.sql

    其中的 xxx 就是你库的名称。username是库的用户名。password是库的密码,稍等一会,等待数据重新导入完成。

7.后续

   数据库导入完成后,7G的脚本生成了一个3G多的库肯定是不行的,其实解决办法也很简单。找个数据库连接工具,比如DBEAVER,链接到你的库。然后随便打开某个表。改个字段值。保存,关闭库。你就会发现库缩小回正常的体积了。

   然后把库放回到项目里重新启动,发现正常,由于我的项目更新频次很低,应该是主要数据都没有丢,如果你们项目使用频次数据更新频次很高,应该还是会丢失一部分数据的,但能恢复极大部分数据,已经可以了。后续多多备份吧。

8.参考

 

posted @ 2024-10-29 10:19  淹死的鱼oOo  阅读(757)  评论(0)    收藏  举报