db4o その11 (ホットバックアップとバグ)

データベースのバックアップ、それもオンライン状態でのホットバックアップ機能は非常に重要だが、db4oはサーバ側で主に使用するObjectServerインタフェースの拡張インタフェースである、ExtObjectServerインタフェースにメソッドとして用意されている。

public interface ExtObjectServer extends ObjectServer{
    public void backup(String path) throws IOException;
    :
    :
    

このメソッドを使用することでデーターベースをクローズすることなくバックアップを行うことができる。

ObjectServer os = Db4o.openServer("roster.db", 0);
ObjectContainer db = os.openClient();
try {
    os.ext().backup("backup.db");
} catch (Exception e) {
    db.rollback();
} finally {
    db.close();
    os.close();
}

このメソッドを使うことで定期的にバックアップを取ることで、物理的な障害等によるデータベースの破損が発生した時に備えることができるだろう。

なお、このbackupメソッド、実はExtObjectContainerインタフェースにも用意されているのだがクライアントサーバモードでサーバに接続した場合はリモートからの接続、インプロセスモード(ポート0で接続)に限らずbackupメソッドを実行すると例外が発生する。

ObjectServer os = Db4o.openServer("roster.db", 0);
ObjectContainer db = os.openClient();
try {
    db.ext().backup("backup.db");
} catch (Exception e) {
    db.rollback();
} finally {
    db.close();
    os.close();
}

実行結果

Backups can not be run from clients and memory files.
com.db4o.ext.Db4oException: Backups can not be run from clients and memory files.
    at com.db4o.internal.Exceptions4.throwRuntimeException(Unknown Source)
    at com.db4o.internal.Exceptions4.throwRuntimeException(Unknown Source)
    at com.db4o.internal.Exceptions4.throwRuntimeException(Unknown Source)
    at com.db4o.internal.cs.ClientObjectContainer.backup(Unknown Source)
    :

接続したクライアントはデータベースではなく、データベースの一部がメモリイメージで転送されているだけなのであり、勝手それぞれにサーバにあるデータベースイメージをバックアップしようとするのは現実的ではないし、意図して禁止しているのだろう。


さて、このバックアップ機能だがdb4oの開発最新版であるversion 6.2ではバグがあって正常に動作しない。

db4o 6.2

現象としてはバックアップ(backupメソッド)が終了せずオープンしたファイルのサイズがどんどん肥大するという、なかなかに怖いバグだ。これはdb4oが内部で使用しているIoAdaptorのデフォルト実装であるCachedIoAdapterの既知のエンバグである。

Discussion Forums » English Forums » db4o User Forum » Re: Backup() doesn't return in version 6.2...

詳しくは別な機会で言及するが、Db4oはデータベースとのIOがIoAdaptorというインタフェースによりプラガブルになっており実装を変えることができる。
環境設定値を司るConfugureインタフェースの規定実装であるConfig4Impl.javaは、以下の定数によりエンバグしているCachedIoAdapterのインスタンスがデフォルトに設定されている。
com.db4o.internal.Config4Impl.javaより

private final static KeySpec IOADAPTER=new KeySpec(new CachedIoAdapter(new RandomAccessFileAdapter()));

従って何も指定を行わずにデータベースをオープンしてbackupメソッドを使用すると、CachedIoAdapterが使われてしまいバグに遭遇する訳だ。

後のバージョンでは当然修正されるはずだが、6.2を使う場合は以下のように明示的にCachedIoAdapterをIoAdaptorに使わないようにしてバグを回避する。(上記リンクのスレッドにもそのように書いてある)

Db4o.configure().io(new RandomAccessFileAdapter());