h2 databaseをリカバリする

プロジェクトでGitBucketを半年以上運用しているのだけど、最近どうもh2(1.4系)の調子が悪い。
利用しているサーバのディスク容量が逼迫しているタイミングで以下のようなエラーが発生し、それ以降調子が悪くなっているように思える。

```
org.h2.jdbc.JdbcSQLException: 一般エラー: "java.lang.IllegalStateException: Corrupt page count -1107358 [1.4.180/3]"
```

```
org.h2.jdbc.JdbcSQLException: 一般エラー: "java.lang.IllegalStateException: Chunk 39556 not found [1.4.180/6]"
General error: "java.lang.IllegalStateException: Chunk 39556 not found [1.4.180/6]"; SQL statement:
```

あと、そんなに容量使っているはずが無いのにdata.mv.dbのサイズが突如<span class="red">8G</span>まで増えたので絶対なにかおかしい！ってことでリカバリを試みてみた。

### 準備

* リカバリツール(というかh2)を以下からダウンロードする
  * [Downloads](http://www.h2database.com/html/download.html)

リカバリツールはmv.dbに直接何かを行うわけではないけど、利用しているGitBucketを止め、data.mv.dbをバックアップしておく。
自分の場合は一旦ローカル環境に落としてきて作業を行った。

### リカバリする

以下にh2のリカバリツールについて説明がある。
実行すると、mv.dbからDDLを吐いてくれる模様。

* [recover_tool](http://www.h2database.com/html/advanced.html#using_recover_tool)
* [Recover](http://h2database.com/javadoc/org/h2/tools/Recover.html)

jarと同一ディレクトリ上にmv.dbファイルを配置してコマンドを実行すると

```bash
$ java -cp h2-1.4.191.jar org.h2.tools.Recover
```

以下の2つのファイルが作成された。

* data.mv.txt
* data.h2.sql

```bash
$ ls -l
total 10462247
-rw-r--r-- 1 tenten0213 Domain Users  729039193 Apr 23 09:41 data.h2.sql
-rw-r--r-- 1 tenten0213 Domain Users 8669241344 Apr 22 22:54 data.mv.db
-rw-r--r-- 1 tenten0213 Domain Users 1313285792 Apr 23 09:40 data.mv.txt
-rw-r--r-- 1 tenten0213 Domain Users         98 Apr 23 09:18 h2.bat
-rwxr-xr-x 1 tenten0213 Domain Users        109 Apr 23 09:18 h2.sh
-rw-r--r-- 1 tenten0213 Domain Users    1763882 Apr 23 09:18 h2-1.4.191.jar
-rw-r--r-- 1 tenten0213 Domain Users        105 Apr 23 09:18 h2w.bat
```

data.mv.txtを見た感じ、mv.dbの構造を表したようなもの？に見える。
ファイルの末尾の方に以下の内容が出力されていて、日付がエラーが発生した日からだから怪しんでいる。(全然的外れかもしれないけど)

```
Last modified: 2016-04-22 22:54:22 (+12465916 s)
File length: 8669241344
The last chunk is not listed
Chunk length: 8111247360
Chunk count: 3906
Used space: 92%
Chunk fill rate: 7%
Chunk fill rate excluding empty chunks: 7%
  Chunk 37480: 2016-04-11 09:09:12 (+11466006 s), 8% used, 404 blocks
  Chunk 37525: 2016-04-11 09:46:13 (+11468227 s), 1% used, 640 blocks
  Chunk 38259: 2016-04-11 17:00:25 (+11494279 s), 1% used, 947 blocks
  Chunk 38586: 2016-04-11 18:57:34 (+11501308 s), 1% used, 907 blocks
  Chunk 38854: 2016-04-12 11:12:28 (+11559802 s), 1% used, 919 blocks
  Chunk 38898: 2016-04-12 11:29:44 (+11560838 s), 1% used, 919 blocks
  Chunk 38904: 2016-04-12 11:30:28 (+11560882 s), 1% used, 935 blocks
  Chunk 39422: 2016-04-12 18:23:31 (+11585665 s), 5% used, 372 blocks
  Chunk 39544: 2016-04-13 07:47:20 (+11633894 s), 1% used, 444 blocks
  Chunk 39580: 2016-04-13 07:47:34 (+11633908 s), 1% used, 536 blocks
  Chunk 39618: 2016-04-13 07:49:11 (+11634005 s), 1% used, 612 blocks
  Chunk 40065: 2016-04-13 08:06:18 (+11635033 s), 98% used, 627 blocks
  Chunk 40066: 2016-04-13 08:06:19 (+11635033 s), 98% used, 686 blocks
  Chunk 40067: 2016-04-13 08:06:19 (+11635033 s), 96% used, 687 blocks
  Chunk 40068: 2016-04-13 08:06:19 (+11635033 s), 97% used, 684 blocks
  Chunk 40071: 2016-04-13 08:06:19 (+11635033 s), 94% used, 78 blocks
:
```

出来上がったDDLを実行する。今度はtoolsのRunScriptを使う。

* [RunScript](http://h2database.com/javadoc/org/h2/tools/RunScript.html)

jdbcのURLは新規でDBを作りたい為`data`ではなく`new`としている。元のファイルを上書きしなければ任意の名前で良い。

```bash
$ java -cp h2-1.4.191.jar org.h2.tools.RunScript -url jdbc:h2:~/backup/h2/bin/new -user sa -password sa -script data.h2.sql -driver org.h2.Driver -showResults
```

new.mv.dbができている。data.mv.dbは8Gなのに450Mくらいしかない！(こっちが普通か)

```bash
$ ls -lh                                                                                                                                
total 11G
-rw-r--r-- 1 tenten0213 Domain Users 696M Apr 23 09:41 data.h2.sql
-rw-r--r-- 1 tenten0213 Domain Users 8.1G Apr 22 22:54 data.mv.db
-rw-r--r-- 1 tenten0213 Domain Users 1.3G Apr 23 09:40 data.mv.txt
-rw-r--r-- 1 tenten0213 Domain Users 2.3K Apr 23 10:42 data.trace.db
-rw-r--r-- 1 tenten0213 Domain Users   98 Apr 23 09:18 h2.bat
-rwxr-xr-x 1 tenten0213 Domain Users  109 Apr 23 09:18 h2.sh
-rw-r--r-- 1 tenten0213 Domain Users 1.7M Apr 23 09:18 h2-1.4.191.jar
-rw-r--r-- 1 tenten0213 Domain Users  105 Apr 23 09:18 h2w.bat
-rw-r--r-- 1 tenten0213 Domain Users 444M Apr 23 11:02 new.mv.db
```

あとは、サーバにあるdata.mv.dbを置き換えて起動すればOK.

最近イロイロあってh2辛かったけど、そろそろh2以外のDBの対応がGitBucketに入る模様なので期待して待っていたい。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr"><a href="https://twitter.com/tenten0213">@tenten0213</a> <a href="https://twitter.com/ebc_2in2crc">@ebc_2in2crc</a> ウッ、もう少しすればMySQLなどでも動くように…。</p>&mdash; Naoki Takezoe (@takezoen) <a href="https://twitter.com/takezoen/status/720025740192821249">April 12, 2016</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


### GitBucket関連の他の記事

* [GitBucketのバックアップ方法 - Qiita](http://qiita.com/tenten0213/items/27ef294193dc85661215)
* [GitBucketで利用しているh2 databaseにターミナルから接続する - Qiita](http://qiita.com/tenten0213/items/79c611c5cd5a3a5aa9ce)