VoltDBの開発者向けドキュメントのまとめ（13章：VoltDBデータベースの保存と復元）

# はじめに

VoltDBの開発者向けの公式ドキュメント[Using VoltDB](https://docs.voltdb.com/UsingVoltDB/index.php)のまとめです。対象のバージョンはv8.3です。

正確に翻訳することや網羅することは目的ではないため、重要でない記述等は削除したり、不足部分は追記しています。

今回は13章です。

現時点でまとめたのは以下の章です。
・[3. データベースの起動](https://qiita.com/mkyz08/items/647459cfe67641e4b888)
・[7. アプリケーション開発の簡略化](https://qiita.com/mkyz08/items/ff9d15cf050af6508964)
・[9. クラスタでVoltDBを使用する](https://qiita.com/mkyz08/items/80f29883a006d1f393e2)
・[13. VoltDBデータベースの保存と復元](https://qiita.com/mkyz08/items/552e83b231e02d47314c)

なお、本投稿のまとめ元である「Using VoltDB」のライセンスはAGPLであり、これらのまとめ投稿はAGPLが適用されます。


# 13. VoltDBデータベースの保存と復元

・VoltDBはメモリ中のデータをディスクに保存し、後から復元できる。この機能をスナップショットと呼ぶ。
・例えば、メンテナンスの場合はクラスタ停止前にデータを保存し、クラスタ起動時に復元できる。
・定期的にバックアップしておくと、障害でクラスタがダウンした場合もフォールバックを提供することができる。

## 13.1. VoltDBクラスタの手動での保存と復元の実行

・VoltDBデータベースの手動での保存・復元はデータベースの構造・スキーマ等を変更する場合に利用できる。
・例えば、K-safety値の変更、ノードごとのサイト数の変更、パーティションテーブルのパーティション列の変更など。

以下の操作で実現できる。
1. データベースの処理を停止する。
  # voltadmin pause
補足：pauseにより読み取り専用モードになりクライアントポートを使用してデータを変更できない。読み取りのトランザクションは許可される。ただし、管理ポート経由では挿入、削除、スキーマ変更などは実行できる。
2. スナップショットをディスクに書き込む。
  # voltadmin save /tmp/voltdb/backup "TestSnapshot" --blocking
3. クラスタをシャットダウンする。
  # voltadmin shutdown
4. スキーマ(DDL)やクラスタ構成(deployment.xml)を変更する。
5. 変更後の構成ファイルでデータベースを初期化する。
  # voltdb init --force
6. 管理モードでクラスタを起動する。
  # voltdb start --pause
7. 必要に応じて、スキーマとストアドプロシージャをリロードする。
8. スナップショットを復元する。
  # voltadmin restore /tmp/voltdb/backup "TestSnapshot"
9. データベースの処理を再開する。
  # voltadmin resume 

2～8の間、データベースでトランザクション処理が実行されないようにpause、--blockingしているのがポイント。


# 13.1.1. VoltDBデータベースの内容を保存する方法

・VoltDBデータベースの内容を保存するには、voltadmin saveコマンドを使用する。
・次の例では、識別子にTestSnapshotを与えて、/tmp/voltdb/backupにスナップショットを作成する。

```
  $ voltadmin save --blocking /tmp/voltdb/backup "TestSnapshot" 
```

・完了するまで他のすべてのトランザクションをブロックする（--blocking） 
・トランザクションをブロックしないで保存することも可能。
・シャットダウン時に手動保存は、確実にトランザクションが完了するようにブロックした方が良い。

・クラスタの一部のノードでだけ失敗する可能性がある。voltadmin saveコマンドを実行したときに、各ノードでファイルのパスが不正であるなどの問題がある場合、メッセージがコンソールに表示されるので、確実に完了したことを確認する。
・引数なしでvoltadmin saveコマンドを実行すると、スナップショットはデフォルトのスナップショットフォルダに保存される。その場合、クラスタ起動時に自動的に復元できる。 


### 13.1.2. VoltDBデータベースの内容を手動で復元する方法

・手動でデフォルトのスナップショットフォルダ（voltdbroot/snapshots）に保存したデータベースは、VoltDBの起動時に自動で復元される。
・コマンドロギングが有効になっている場合は、スナップショット後のログも復元される。
・ただし、前のスナップショットまたは別の場所に格納されているスナップショットを復元する場合で復元する場合は、voltdb startでの自動復元ではなく手動復元を実行する。

・手動で復元するにはvoltadmin restoreコマンドを使用する。
・たとえば、構成を変更した場合は、--forceフラグを使用して新しい構成ファイルでルート・ディレクトリを再初期化した後に手動で復元する。 

```
$ voltdb init --config=new_deployment.xml --force 
```

・再構成する空のデータベースが作成される。「-pause」を指定し管理モードで起動する。

```
$ voltdb start --pause 
```

・復元時にスナップショットを指定して復元できる。
例）

```
$ voltadmin restore /tmp/voltdb/backup "TestSnapshot"
$ voltadmin resume 
（resumeで管理モードを終了）
```

### 13.1.3. 保存と復元を使用したクラスタ構成の変更

VoltDBデータベースのほとんどの変更は、実行中に行うことができるが、保存と復元を利用することで、実行中のクラスタではできないデータベースおよびクラスタ構成を変更することは可能。
たとえば、次の操作を実行できる。

・保存と復元時にクラスタにノードを追加または削除する。
・次のようなスキーマやストアドプロシージャの変更ができる。
　・パーティションテーブルをレプリケーションに変更する。
　・パーティションテーブルのパーティション列を変更する。
　・データを持つテーブルにユニークインデックスを追加する。 
・ホストのサイト数を変更する
・K-safetyを変更する 


#### 13.1.3.1. データベースへのノードの追加と削除

クラスタにノードを追加するには次の手順を実行する。

1. voltadmin saveコマンドを使用してデータベースを保存する。
2. 各ノードをシャットダウンして初期化する。新しいノードも初期化する。
3. voltdb startコマンドの--count引数でノード追加後のサーバー数を指定してクラスタを開始する。
4. voltadmin restoreコマンドを使用してデータベースを復元する。 

・スナップショットが復元されると、データベース（およびパーティション）は新しいクラスタ構成となり、新しいサーバへデータが再配布される。
・クラスタからノードを削除することもできる。


#### 13.1.3.2. データベーススキーマとストアドプロシージャの変更

・データベーススキーマを変更するにはsqlcmdユーティリティでDDLを実行する。
・ストアドプロシージャの更新はLOAD CLASSESおよびREMOVE CLASSESディレクティブを使用する。
・ただし、実行中のデータベースでは、テーブルにデータが含まれている場合にパーティション化列を変更するなどのいくつかの変更は実行できず、保存と復元を使用する必要がある。

・保存と復元の間でデータベース・スキーマまたはストアド・プロシージャを変更するには、ソース・ファイル（データベースDDL）とJavaストアドプロシージャを準備し、以下を実行する。

1.voltadmin saveコマンドを使用してデータベースを保存する。
2.シャットダウンして各ノードのデータベースルートディレクトリを再初期化する。
3.voltdb startコマンドを使用してクラスタを起動する。
4.sqlcmdを使用して、変更されたスキーマとストアドプロシージャをロードする。
5.voltadmin restoreコマンドを使用してデータベースの内容を復元する。