Yet another OSS DB:Firebird(2)

データベースファイルの内部構造を探ってみた

 

第2回の今回は、Firebirdが管理するデータベースファイルの内部構造を探っていきます。基本的な仕組みを理解したらGLinkというツールの実装を参考にしながら、処理の仕組みをみてみましょう。

1つのバイナリファイル

 Firebirdの特徴の1つとして、データベースファイルがたった1ファイルだけである点が挙げられます。データベースサーバを停止してしまえば、この1つのファイルをコピーするだけでもバックアップが可能なので、大変手軽に扱えることの象徴みたいなものになっています(2つ目、3つ目のファイルを追加することは可能で、これを2次ファイルといいます)。

 ほかのデータベースではどうかというと、例えばPostgreSQLでは$PG_DATAで指定したデータディレクトリ以下に多数のディレクトリとファイルが作成されます。テーブルとインデックスはそれぞれ1ファイルになり、またファイル名は単なる数字になっています。

 さて、Firebirdのデータベースファイルそのものは単なるバイナリファイルにすぎません。手元に置けば直接読み書きすることも可能です。Firebirdのデータベースファイルの形式はODS(On Disk Structure)と呼ばれ、Firebird 1.0系のODS 10から最新のFirebird 2.1のODS 11.1までいくつかの改良が行われています。今回はこのFirebirdのヘッダをデータベースファイルから直接読み書きしてみることにチャレンジしたいと思います。

ODSの変遷
Firebirdの
バージョン
ODSの
バージョン
内容
Firebird
1.0〜1.0.3
ODS10 ODS10.1への変換は、バックアップ/リストアが必要です
Firebird
1.5〜1.5.5
ODS10.1 Firebird1.0はODS10.1のデータベースを扱えます
Firebird
2.0〜2.0.4
ODS11 ODS11への変換は、バックアップ/リストアが必要です
Firebird
2.1〜2.1.1
ODS11.1 ODS11.1への変換は、バックアップ/リストアが必要です。また、Firebird2.0,1.5,1.0では、ODS11.1は扱えません

Page types

 Firebirdのデータベースは、データベースを作成する際に指定する固定長のページサイズの整数倍の大きさのファイルになります。

Firebirdのページサイズ

 Firebirdのデータベースエンジンは、データベースファイルへアクセスする際にはまず、先頭の1024bytes(ヘッダページ)を読み込み、ヘッダページの情報を参照することでデータベースのページサイズがいくつであるかを確認します。

 ページサイズはデータベースの作成時に1024/2048/4096/8192/16384bytesを指定できますが、運用中に変更することはできません。どうしても運用中に変更したい場合は、いったんバックアップをしたうえで、リストア時に指定することで変更できます

注:現在開発中のver.2.5以降では、1024/2048バイトのページサイズは使用できなくなります。

ページサイズの選択肢が多い理由

 どうしてデータベースのページサイズを細かく指定できるようになっているのかというと、データベースシステムのボトルネックは大抵の場合、ディスクのI/Oに発生するため、Firebirdのエンジンが開発された当初の1980年代には1024bytesのページサイズで十分だったものが時代を経るにつれて拡張されてきたためです。実際、16384bytesのページサイズについては、InterBaseがオープンソース化された際に、Firebird 1.0で初めて導入されたものです。

メモリサイズの制限

 また、データベースのページサイズは同時に、Firebirdのバッファサイズ、つまりメモリ使用に関してもそのサイズを制限します。Firebirdは、Classicサーバ版(プロセスモデル)では、プロセスごとに規定値で75ページのデータベースバッファを使用します。つまり、1024bytesのページサイズの場合は75Kbytes、16384bytesのページサイズの場合には1.2Mbytesのメモリを使用することになります。Superサーバ版では2048ページが規定値のため、16384bytesのページサイズでは32Mbytesのメモリを使用することになります。

 注意しなければいけないのは、Superサーバ版では1プロセスのみがデータベースバッファを保持するため、32Mbytesであろうが128Mbytesであろうが設定した値を超えるメモリは使用されませんが、Classicサーバ版では「各クライアントからの接続ごと」にプロセスが生成されるため、同時接続する最大クライアント数が増えれば増えるだけメモリを使用することになります。

ページタイプの種類と目的

 さて、Firebirdのデータベースエンジンに読み込まれるそれぞれのページは、それぞれ特定の目的で使用され、そのPage typeは別表のとおりになります。

  1. データベースヘッダページ
  2. ページインベントリページ
  3. トランザクションインベントリページ
  4. ポインタページ
  5. データページ
  6. インデックスルートページ
  7. インデックスページ
  8. ブロブデータページ
  9. ジェネレータページ
  10. ログインフォページ
データベースのページ構造fig1

 10番目のログインフォページはライトアヘッドログに関する情報を格納するPage typeです。Firebirdではライトアヘッドログに関する機能は過去に一度実装されたものの、現在は実装から外されています。しかし、このページ自体はデータベースファイルの3番目のページに必ず存在しています。いってみれば、“へそ”みたいなものですね。実際のods.hの定義を以下に示します。

ods.hの定義
/* Page types */
const SCHAR pag_undefined = 0;
const SCHAR pag_header = 1;       /* Database header page */
const SCHAR pag_pages = 2;        /* Page inventory page */
const SCHAR pag_transactions = 3; /* Transaction inventory page */
const SCHAR pag_pointer = 4;      /* Pointer page */
const SCHAR pag_data = 5;         /* Data page */
const SCHAR pag_root = 6;         /* Index root page */
const SCHAR pag_index = 7;        /* Index (B-tree) page */
const SCHAR pag_blob = 8;         /* Blob data page */
const SCHAR pag_ids = 9;          /* Gen-ids */
const SCHAR pag_log = 10;         // Write ahead log information DEPRECATED
const SCHAR pag_max = 10;         /* Max page type */
Basic page header
  1/3 次のページへ

Index
Yet another OSS DB:Firebird(2)
データベースファイルの内部構造を探ってみた
→ Page 1
・1つのバイナリファイル
   Page types
   Firebirdのページサイズ
   ページサイズの選択肢が多い理由
   メモリサイズの制限
   ページタイプの種類と目的
   Page 2
・ページファイルの中身(Basic page header)
・Glink
   Page 3
・GlinkのソースコードからFirebirdの実装を見る
   Glinkの実装を追いかける
   謎の数値40587を探る
   バイナリエディタでささっと調査
   clumpletsの実装チェックと置き換え
   update_db_header()


Yet another OSS DB:Firebird



Database Expert フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Database Expert 記事ランキング

本日月間