3

我们的 Perfino 服务器最近崩溃了,从那时起记录如下所示的错误。(有一些线索暗示 OutOfMemory 会导致数据库损坏。)

建议:'可能的解决方案:使用恢复工具'。但是官方 perfino 文档和日志都没有提供更多关于如何进行的说明。

所以这里的问题是:如何使用恢复工具?

堆栈跟踪:

ERROR [collector] server: could not load transaction data
org.h2.jdbc.JdbcSQLException: File corrupted while reading record: "[495834] stream data key:64898 pos:11 remaining:0". Possible solution: use the recovery tool; SQL statement:
SELECT value FROM transaction_names WHERE id=? [90030-176]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:344)
    at org.h2.message.DbException.get(DbException.java:178)
    at org.h2.message.DbException.get(DbException.java:154)
    at org.h2.index.PageDataIndex.getPage(PageDataIndex.java:242)
    at org.h2.index.PageDataNode.getNextPage(PageDataNode.java:233)
    at org.h2.index.PageDataLeaf.getNextPage(PageDataLeaf.java:400)
    at org.h2.index.PageDataCursor.nextRow(PageDataCursor.java:95)
    at org.h2.index.PageDataCursor.next(PageDataCursor.java:53)
    at org.h2.index.IndexCursor.next(IndexCursor.java:278)
    at org.h2.table.TableFilter.next(TableFilter.java:361)
    at org.h2.command.dml.Select.queryFlat(Select.java:533)
    at org.h2.command.dml.Select.queryWithoutCache(Select.java:646)
    at org.h2.command.dml.Query.query(Query.java:323)
    at org.h2.command.dml.Query.query(Query.java:291)
    at org.h2.command.dml.Query.query(Query.java:37)
    at org.h2.command.CommandContainer.query(CommandContainer.java:91)
    at org.h2.command.Command.executeQuery(Command.java:197)
    at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:109)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:353)
    at com.perfino.a.f.b.a.a(ejt:70)
    at com.perfino.a.f.o.a(ejt:880)
    at com.perfino.a.f.o.a(ejt:928)
    at com.perfino.a.f.o.a(ejt:60)
    at com.perfino.a.f.aa.a(ejt:783)
    at com.perfino.a.f.o.a(ejt:847)
    at com.perfino.a.f.o.a(ejt:792)
    at com.perfino.a.f.o.a(ejt:787)
    at com.perfino.a.f.o.a(ejt:60)
    at com.perfino.a.f.ac.a(ejt:1011)
    at com.perfino.b.a.b(ejt:68)
    at com.perfino.b.a.c(ejt:82)
    at com.perfino.a.f.o.a(ejt:1006)
    at com.perfino.a.i.b.d.a(ejt:168)
    at com.perfino.a.i.b.d.b(ejt:155)
    at com.perfino.a.i.b.d.b(ejt:52)
    at com.perfino.a.i.b.d.a(ejt:45)
    at com.perfino.a.i.a.b.a(ejt:94)
    at com.perfino.a.c.a.b(ejt:105)
    at com.perfino.a.c.a.a(ejt:37)
    at com.perfino.a.c.c.run(ejt:57)
    at java.lang.Thread.run(Thread.java:745)
4

2 回答 2

9

注意:我无法使用下面描述的过程恢复我的数据库。我仍然保留这篇文章作为参考,因为成功恢复的概率将取决于数据库的损坏程度,并且没有证据表明此过程无效。


Perfino 默认使用H2 数据库引擎作为其持久性存储。H2有一个恢复工具和一个运行脚本工具来导入sql语句:

# 1. Create a dump of the current database using the tool [1]
# This tool creates a 'config.h2.sql' and a 'perfino.h2.sql' db dump
cd ${PERFINO_DATA_DIR}
java -cp ${PATH_TO_H2_LIB}/h2*.jar org.h2.tools.Recover

# 2. Rename the corrupt database file to e.g. *bkp
mv perfino.h2.db perfino.h2.db.bkp

# 3. Import the dump from step 1, ignoring errors
java -cp ${PATH_TO_H2_LIB}/h2*.jar \
     org.h2.tools.RunScript \
     -url jdbc:h2:${PERFINO_DATA_DIR}/db/perfino \
     -script perfino.h2.sql -checkResults

[1]:Perfino 包含一个版本的h2.jarunder ${PERFINO_INSTALL_DIR}/lib/common/h2.jar。您当然可以下载官方 jar并尝试使用它,但就我而言,我只能使用 perfino 提供的 jar 来恢复数据库。


这对我来说失败了

Exception in thread "main" org.h2.jdbc.JdbcSQLException: Feature not supported: "Restore page store recovery SQL script can only be restored to a PageStore file".

如果您遇到这种情况,请尝试:

# 1. Delete database and mv files
cd ${PERFINO_DATA_DIR}
rm perfino.h2.db perfino.mv.db

# 2. Create a PageStore database manually
touch perfino.h2.db

# 3. try with MV_STORE=FALSE on the url [2]
java -cp ${PATH_TO_H2_LIB}/h2*.jar \
     org.h2.tools.RunScript \
     -url jdbc:h2:${PERFINO_DATA_DIR}/db/perfino;MV_STORE=FALSE \
     -checkResults \
     -continueOnError

[2]:强制 h2 重新创建页面存储数据库而不是新的存储引擎(请参阅元数据库中的此线程

于 2017-01-27T16:32:03.383 回答
2

我发现这篇文章试图修复 Confluence 内部 h2 数据库,这对我有用。这是我的 GitHub 上的一个 shell 脚本作为我所做的要点 - 你必须根据你的环境进行调整。

于 2018-06-20T15:46:01.830 回答