Extensible Storage Engine のアーキテクチャ

 

適用先: Exchange Server 2007 SP3, Exchange Server 2007 SP2, Exchange Server 2007 SP1, Exchange Server 2007

トピックの最終更新日: 2008-11-19

ハブ トランスポート サーバーおよびエッジ トランスポート サーバー上の Exchange メールボックス データベースとキューでは、Extensible Storage Engine (ESE) データベースを使用します。ESE は、DML (データ操作言語) および DDL (データ定義言語) 機能を完全に備えたマルチユーザー ISAM (索引順次アクセス方式) テーブル マネージャです。ESE によって、アプリケーションはレコードを格納し、インデックスを作成してさまざまな方法でこれらのレコードにアクセスできるようになります。

ESE には、次の 2 つのバージョンがあります。

  • ESENTl   Active Directory や、多くの Microsoft Windows コンポーネント用のデータベース エンジンです。Active Directory 実装の ESENT は他のバージョンの ESE (5 MB ログ ファイルと 4 KB ページ サイズを使用) とは異なり、10 MB ログ ファイルと 8 KB ページを使用します。
  • ESE98   Exchange 2000 Server、Exchange Server 2003、および Exchange Server 2007 のデータベース エンジンです。
  • ESE は、以前は Joint Engine Technology (JET) Blue と呼ばれていました。JET Blue は、Microsoft Access で使用されているバージョンの JET ("JET Red" と呼ばれる) とは異なります。

トランザクション

ESE は、高度なトランザクション ベースのデータベース エンジンです。トランザクションとは、原子 (それ以上分割できない) 単位として処理される一連の処理のことです。トランザクションでは、すべての処理が実行されて完全に保存されるか、まったく処理が実行されないかのいずれかになります。たとえば、受信トレイのメッセージを削除済みアイテム フォルダに移動する場合に必要な処理について考えてみます。あるフォルダからメッセージが削除され、別のフォルダに追加され、フォルダのプロパティが更新されます。障害が発生した場合に、メッセージのコピーが 2 つ作成されたり、まったく作成されなかったり、フォルダのプロパティ値 (アイテム数など) が実際のフォルダ内容と矛盾したりするのは問題です。

このような問題を防ぐために、ESE ではトランザクション内に処理を組み込みます。ESE は、トランザクションがデータベース ファイルにコミットされるまで、どの処理も完全に適用されないようにします。トランザクションがデータベース ファイルにコミットされると、すべての処理が完全に適用されます。

サーバーが応答を停止した場合は、サーバーを再起動すると、ESE が自動回復を処理してコミットされていないトランザクションをロールバックします。トランザクションがコミットされる前に ESE に障害が発生した場合は、トランザクション全体がロールバックされ、トランザクションが発生していない場合と同じ状態になります。トランザクションがコミットされた後で ESE が応答を停止した場合は、トランザクション全体が保持され、クライアントで変更内容を表示することができます。

ACID トランザクション

前のセクションで示したようなトランザクションは、一般的に ACID トランザクションと呼ばれています。ACID は、次の属性の略語です。

  • 原子性 (Atomic)   トランザクションの状態の変更が "すべて" または "なし" であることを示します。原子状態の変更には、データベースの変更や、変換器上のメッセージとアクションが含まれます。
  • 一貫性 (Consistent)   トランザクションが状態の正確な変換であることを示します。グループとして実行される処理は、状態に関連付けられた整合性の制約のいずれにも違反しません。これには、トランザクションが正確なプログラムであることが必要です。
  • 分離性 (Isolated)  トランザクションを同時に実行した場合でも、各トランザクション (t) からは、もう一方のトランザクションが t の前か t の後 (前と後の両方ではなく) に実行されたように見えることを示します。
  • 持続性 (Durable)   システムが応答を停止した場合でも、コミットされたトランザクションがデータベースに保持されます。

バージョン ストア

バージョン ストアを使用すると、ESE は現在のトランザクションの追跡と管理を行うことができます。したがって、ESE は、ACID テストのうち、分離性と一貫性の部分に合格することができます。バージョン ストアは、データベースで行われた変更のリストをメモリ内に保持します。

バージョン ストアは、次のような状況で使用します。

  • ロールバック   トランザクションをロールバックする必要がある場合、実行した処理の一覧を取得するために、バージョン ストアを確認します。トランザクションをロールバックするには、すべての処理を反対方向に実行します。
  • 書き込み競合の検出   2 つの異なるセッションが同じレコードの変更を試みると、バージョン ストアがこれを通知して 2 番目の変更を拒否します。
  • 反復可能読み取り   セッションがトランザクションを開始すると、表示中のレコードを他のセッションが変更した場合でも、常に同じデータベースを表示します。セッションがレコードを読み取る場合、そのセッションで表示する必要があるレコードのバージョンを判断するためにバージョン ストアに問い合わせます。反復可能読み取りでは、クライアントのトランザクション開始後は、変更が他のクライアントやセッションによって行われたかどうかにかかわらず、クライアントはトランザクション開始時のデータベースの状態を読み取るという分離レベルが実現されます。反復可能読み取りは、バージョン ストアを使用して実装されます。データベースに対して行われた変更のメモリ内リストを使用することで、特定のセッションで表示する必要があるレコード ビューを判断することができます。
  • 変更前イメージの遅延ロギング   ESE のログ出力データを他の同等のデータベース エンジンよりも少なくする、複雑な最適化です。

スナップショット分離

トランザクションが開始されると、そのセッションでは、トランザクション開始時の状態にセッション自体への変更が反映された、単一で一貫性のあるデータベース イメージが表示されることが ESE によって保証されます。他のセッションでもデータの変更とトランザクションのコミットが可能なため、これらの変更はコミット前に開始されたトランザクションには不可視です。ユーザーは、最新バージョンのレコードを表示している場合にのみそのレコードを変更できます。そうでない場合は、更新は JET_errWriteConflict で失敗します。最新のトランザクションより前のバージョンは自動的に破棄されます。

ESE は、スナップショット分離と呼ばれるトランザクションの分離レベルを特長とします。スナップショット分離レベルを使用すると、ユーザーは時間的推移に沿った一貫したデータベース ビューを使用して、最後にコミットされた行にアクセスできます。スナップショット分離とは、『A Critique of ANSI SQL Isolation Levels』で最初に紹介された同時実行制御アルゴリズムです。スナップショット分離は ESE によって、反復可能読み取りを使用することにより実装されます。

ESE データベース構造

リッチテキスト データベース ファイル内のすべてのデータは、B+ ツリーに格納されます。B+ ツリーの "B" はバランス (balanced) を意味します。"ツリー" は、ファイル システムのフォルダ構造と似た配置のことで、ルートがアイテム (データベース ページ) の親であり、他のアイテムの親でもあります。B+ ツリーは、ディスク上のデータへの高速アクセスができるように設計されています。ディスクの読み取りとディスクへの書き込みは、メモリの読み取りとメモリへの書き込みよりもはるかに遅いため、B+ ツリーは 8 KB のページに分割されています。これにより、ESE は、最小限の数のディスク I/O で必要なデータを取得できます。ESE データベースには、最大 2^31 (2 の 31 乗) の 8 KB ページを収容できます。つまり、合計最大データベース サイズは約 16 TB です。実際には、データベース サイズは、バックアップ、復元、およびデータベースでのその他の保守操作 (オフラインでの最適化、データベースの修復など) を適切なタイミングで行う能力によってのみ制限されます。

データベース ページ

ESE のページ サイズは、それを使用するアプリケーションによって定義されます。たとえば、ESE98 (Exchange 2000 Server と Exchange Server 2003) は 4 KB ページを使用するのに対し、ESENT (Active Directory) は 8 KB ページを使用します。これらの 4 KB ページと 8 KB ページにはそれぞれ、他のページを指すポインタ、または B+ ツリーに格納されている実データを指すポインタが含まれています。ポインタとデータ ページはファイル内に混在しています。

パフォーマンスを最大限に高めるため、ページはメモリ バッファ内にできるだけ長くキャッシュされます。これにより、ディスクにアクセスする必要性が少なくなります。各ページは 40 バイトのページ ヘッダーで始まり、ヘッダーには以下の値が含まれています。

  • pgnoThis   ページ番号を示す値です。
  • DbtimeDirtied   ページが最後に変更された Dbtime を示す値です。
  • pgnoPrev   リーフの左側のページのページ番号を示す値です。
  • pgnoNext   リーフの右側のページのページ番号を示す値です。
  • ObjidFDP   Father of the Data Page (FDP) と呼ばれるデータベース内の特殊なページの Object ID を示す値です。この Object ID は、このページが属する B+ ツリーを示します。FDP ページは修復時に使用されます。
  • cbFree   ページ上で使用できるバイト数を示す値です。
  • cbUncommittedFree   ページ上で使用できるコミットされていないバイト数 (空きバイトだが、ロールバックによって再生利用できるバイト) を示す値です。
  • ibMicFree   ページの最上部にある、次に使用できるバイトのページ オフセットを示す値です。

ECC チェックサム

エラー訂正コード (ECC) チェックサムによって、データベース ページ (.edb ファイル内) のシングル ビット エラーの訂正が可能になります。

最新のチェックサム形式は 2 つの 32 ビット チェックサムで構成されています。1 つは XOR チェックサムで、ページ番号が計算のシードとして使用されます。2 番目の 32 ビット チェックサムは ECC チェックサムで、ページ上のシングル ビット エラーの訂正を可能にします。

データベースの整合性と -1018 エラー

ページの読み取りが行われると、ESE はページ上のフラグを調べて、ページに最新のチェックサム形式があるかどうかを確認します。次に、適切なチェックサムが計算されます。最新形式のチェックサムと一致しないチェックサムがある場合、ESE はエラーの訂正を試みます。エラーを自動的に訂正できない場合は、Exchange によって -1018 エラーが報告されます。

Exchange ストアが以下のいずれかの操作を行った場合、Exchange ストア自体が -1018 エラーを生成する場合があります。

  • 間違ったチェックサムを持つページを作成した。
  • ページを正しく作成したが、オペレーティング システムに対して間違った場所にページを書き込むよう通知した。

システム管理者は、-1018 エラーが発生した場合や、サーバーでハードウェア診断テストを実行しても何も問題が報告されない場合、ハードウェアが最初の分析にパスしたため Exchange が問題の原因になっていると結論付ける場合があります。

マイクロソフトやハードウェア ベンダの調査によって、実際にデータベース ファイルの破損の原因となっている捕らえにくい問題が、ハードウェア、ファームウェア、またはデバイス ドライバで検出されることがよくあります。

通常の診断テストでは、いくつかの理由から、すべての一時的な障害が検出されない場合があります。ファームウェアやドライバ ソフトウェアの問題は、診断プログラムの機能の範囲外である場合があります。診断テストは、長時間に及ぶ実行や複雑な読み込みを適切にシミュレートできない場合があります。また、診断監視機能やデバッグのログ出力を追加することで、問題の再発を防ぐための十分な変更をシステムに加えることができる場合もあります。

チェックサムを生成し、データベース ファイルにページを書き込む Exchange のメカニズムは簡潔で安定性が高いため、-1018 エラーはおそらく Exchange 以外の要因によって引き起こされています。チェックサムと正しくないページを検出するメカニズムは簡潔で信頼性が高く、最初の Exchange がリリースされて以来、データベース バージョン間でのデータベース ページ形式の変更に適合するためのマイナーな変更を除き、基本的に変わっていません。

チェックサムは、ページ番号自体などの他のすべてのデータがページに書き込まれた後で、ディスクに書き込まれようとしているページに対して生成されます。Exchange はページにチェックサムを追加した後、Microsoft Windows Server オペレーティング システムに対し、公開されている標準の Windows Server API を使用してディスクにページを書き込むよう指示します。

チェックサムがページに対して正しく生成されても、そのページがハード ディスクの間違った場所に書き込まれる可能性があります。これは、"ビット反転" などの一時的なメモリ エラーによって発生します。たとえば、Exchange が新しいバージョンの 70 ページを作成するとします。そのページ自体にエラーはありませんが、ディスク コントローラやオペレーティング システムによって使用されるページ番号のコピーがランダムに変更されます。この問題は、不安定なメモリ セルによって 70 (バイナリ 1000110) が 6 (バイナリ 000110) に変更された場合に発生する可能性があります。ページのチェックサムは正しいのですが、データベース内のページの場所が間違っています。Exchange は、論理ページ番号がページの物理的な場所と一致しないことを検出したとき、そのページに対して -1018 エラーを報告します。

Exchange がページ自体に間違ったページ番号を書き込んだ場合に、別の種類のページ番号エラー (Exchange が原因) が発生する可能性があります。ただしこの場合は、-1018 エラーではなく別のエラーが発生します。Exchange が 70 ページに 71 を書き込み、70 ページでチェックサムを正しく実行した場合、そのページが 71 の場所に書き込まれ、ページ番号テストとチェックサム テストの両方に合格します。

一般に、Exchange データベースで 1 回の -1018 エラーが報告されても、データベースが停止する原因になったり、-1018 エラー自体が存在する以外の現象が起きることはありません。ページはアクセス頻度の低いフォルダ ([送信済みアイテム] フォルダや [削除済みアイテム] フォルダなど) に存在するか、めったに開かれない添付ファイルか空の添付ファイルに存在します。

1 回の -1018 エラーが大規模なデータ損失を引き起こす可能性はないと考えられますが、-1018 エラーは記憶域システムが少なくとも 1 度データを確実に格納または取得しなかったことを証明するものであるため、このエラーには注意が必要です。-1018 エラーは 2 度と起こらない一時的な問題である可能性もありますが、徐々に悪化する問題を早期に警告するエラーである可能性もあります。最初の -1018 エラーはデータベース内の空のページに存在していても、次にどのページが破損するかわかりません。重要なグローバル テーブルが破損すると、データベースが起動せず、データベースの修復が部分的または完全に失敗する可能性があります。

-1018 エラーがログに記録された場合は、根本的な原因を検出して取り除くまではデータベースに障害が発生したりランダムな損失が発生したりする可能性があることを考慮し、それに備える必要があります。

データベース ツリーのバランス維持

ESE の主な機能の 1 つに、データベース ツリーのバランスを常に維持する機能があります。ツリーのバランス維持の処理は、すべてのページが分割または結合されたときに終了します。次の図に示すように、ツリーのルート レベルには、常にツリーのリーフ レベルと同じ数のノードが存在します。したがって、ツリーのバランスが取れています。

B ツリー

バランス ツリー

ESE の観点では、データベース テーブルは B+ ツリーの集合です。各テーブルはデータを含む 1 つの B+ ツリーで構成されていますが、多くのセカンダリ インデックスの B+ ツリーを使用して、さまざまなビューのデータを提供することができます。テーブルの列またはフィールドが広くなりすぎて B+ ツリーに格納できない場合は、Long-Value ツリーという名前の別の B+ ツリーに分割されます。

これらのテーブルとそれらに関連付けられた B+ ツリーの定義は、システム カタログという名前の別の B+ ツリーに格納されます。システム カタログの損失は深刻な問題です。したがって、ESE はこの B+ ツリーの 2 つの同じコピーを各データベースに保持します。

分割

ページがほぼいっぱいになると、約半分のデータがセカンダリ ページに配置され、追加のキーがセカンダリ ページの親ページに配置されます。この処理は、親ページもいっぱいでない限り実行されます。この場合、このページの親ページは分割され、親ページにポインタが追加されます。最終的に、ルート ブロック以下のすべてのポインタ ページを分割することが必要になる場合があります。ルート ブロックの分割が必要な場合は、ツリーに追加レベルのページが挿入されます。たとえて言えば、ツリーの高さが高くなります。

結合

ページはほぼ空になると、隣接するページに結合され、親ページのポインタが更新されます。また、必要に応じて親ページも結合されます。最終的に、ルート ブロック以下のすべてのポインタ ページが結合されると、ツリーの高さが低くなります。リーフ (データ) を取得するために、ESE はルート ノードから開始し、目的のリーフ ノードに達するまでページ ポインタをたどります。

ファンアウト

ESE B+ ツリーのツリー構造には、非常に高度なファンアウト機能があります。高度なファンアウトとは、ESE が 4 回以下のディスク読み取り (3 つのポインタ ページとデータ ページ自体) だけで 50 GB テーブル内のどのデータにも到達できることを意味します。ESE は、4 KB ページごとに 200 を超えるページ ポインタを格納するため、親/子レベルが最も少ない数のツリー (shallow ツリーとも呼ばれます) を使用できるようになります。ESE は、現在のツリーのキーも格納します。このキーによって、現在のツリーをすばやく検索することができます。上の図は、3 つの親/子レベルがあるツリーです。4 つの親/子レベルがあるツリーには数 GB のデータを格納できます。

インデックス

従来の B+ ツリーは、ある特定の方法でのみインデックス付けされています。この方法では 1 つのキーを使用し、データはそのキーを使用して取得される必要があります。たとえば、メッセージ テーブルのレコードは、メッセージ転送サービス (MTS) ID と呼ばれるメッセージの一意の識別子でインデックス付けされます。ただし、ユーザーは、よりユーザー フレンドリな形式で配列されたメッセージ テーブルにデータを表示することを望むと考えられます。

インデックス、特にセカンダリ インデックスは、データの取得に使用されます。各セカンダリ インデックスは、選択されたセカンダリ キーを主キーにマッピングする別の B+ ツリーです。これによって、インデックスを付けたデータと比べて B+ ツリーが小さくなります。

セカンダリ インデックスがどのように使用されるかを理解するために、メッセージ フォルダにメッセージを表示する方法をユーザーが変更すると何が起こるかを考えます。Outlook のフォルダ ビューを受信日時ではなく件名で並べ替えるように変更すると、Outlook では、ストアと ESE によってメッセージ フォルダ テーブル上に新しいセカンダリ インデックスが作成されます。

大きいフォルダのビューを最初に変更するとき、遅延が発生します。サーバーを詳しく調べると、ディスク アクティビティに小さなスパイクがあるのがわかります。再度そのビューに切り替えると、インデックスは既に作成されており、応答が大幅に速くなります。

Microsoft Exchange Information Store サービスのセカンダリ インデックス B+ ツリーは、8 日間存続します。使用されない場合は、Microsoft Exchange Information Store サービスによってバックグラウンド操作として削除されます。

Long-Value

ESE の列またはレコードは、データ B+ ツリー内のページにまたがることはできません。4 KB のページの境界を分割する値 (メッセージのメッセージ本文である PR_BODY など) があります。これらの値は Long-Value (LV) と呼ばれます。テーブルの Long-Value B+ ツリーは、これらの大きな値を格納するために使用されます。

ESE テーブルにデータが入力され、そのデータがデータ B+ ツリーに収容するには大きすぎる場合、データは 4 KB のページに分割され、テーブルの別の Long-Value B+ ツリーに格納されます。データ B+ ツリーのレコードには、Long-Value を指すポインタが含まれています。このポインタは Long-Value ID (LID) と呼ばれ、レコードに LID 256 を指すポインタがあることを意味します。

レコード形式

B+ ツリーの集合はテーブルを表し、テーブルは行の集合です。行はレコードとも呼ばれます。レコードは多くの列で構成されています。レコードの最大サイズおよび 1 つのレコードに表示される列の数は、データベースのページ サイズからヘッダーのサイズを引いた数によって決まります。ESE には 4 KB のページ サイズがあります。したがって、最大レコード サイズは約 4,050 バイト (4,096 バイトからページ ヘッダーのサイズを引いた数) になります。

列データ型

各列の定義で、列に格納されるデータ型を指定する必要があります。ESE がサポートするデータ型を次の表に示します。

Extensible Storage Engine の列データ型

列データ型 説明

Bit

NULL、0、または 0 以外

Unsigned Byte

1 バイトの符号なし整数

Short

2 バイトの符号付き整数

Unsigned Short

2 バイトの符号なし整数

Long

4 バイトの符号付き整数

Unsigned Long

4 バイトの符号なし整数

LongLong

8 バイトの符号付き整数

Currency

8 バイトの符号付き整数

IEEE Single

4 バイトの浮動小数点数

IEEE Double

8 バイトの浮動小数点数

Date Time

8 バイトの日付/時刻 (整数部は日付、小数部は時刻)

GUID

16 バイトの一意の識別子

Binary

255 バイト以下のバイナリ文字列

Text

255 バイト以下の ANSI または Unicode 文字列

Long Binary

2 GB 未満の大きな値のバイナリ文字列

Long Text

2 GB 未満の大きな値の ANSI または Unicode 文字列

列データ型は 2 つのカテゴリに分類されます。最初のカテゴリは、固定列と可変列です。2 番目のカテゴリはタグ付けされた列です。各列は、16 バイトの FIELD 構造体と列名のサイズとして定義されています。

ESE データベース内にテーブルが作成されると、テーブルは FIELD 構造体の配列を使用して定義されます。この配列によって、テーブル内の個々の列が識別されます。この配列内では、各列は列 ID と呼ばれるインデックス値で表されます。配列 [0]、配列 [1] など、ID で配列メンバを参照できる通常の配列に似ています。列には ID によってすばやくアクセスできますが、列名での検索には FIELD 構造体の配列を線形にスキャンする必要があります。

固定列と可変列

固定列には固定長のデータが含まれています。各レコードは、値が定義されていない場合でも、定義済みのレコード領域を占めます。データ型 ID 1 ~ 10 は、固定列として定義できます。各テーブルには、最大 126 (列 ID 1 ~ 127) までの固定列を定義できます。

可変列は最大 256 バイトのデータを含むことができます。オフセット配列は、最上位の可変列セットを持つレコードに格納されます。各列に 2 バイトが必要です。データ型 ID 10 ~ 11 は、可変列として定義できます。各テーブルには 127 (列 ID 128 ~ 256) までの可変列を定義できます。

タグ付けされた列

ESE では、ほとんど発生しない列や単一のレコード内で複数発生する列を、タグ付けされた列として定義します。未定義のタグ付けされた列によって領域のオーバーヘッドは発生しません。タグ付けされた列は、同じレコード内で繰り返し発生する可能性があります。タグ付けされた列がセカンダリ インデックスで表される場合は、個々の列が発生するたびにインデックスで参照されます。

タグ付けされた列は、可変長のデータを無制限に含むことができます。列 ID と長さは、データと共に格納されます。すべてのデータ型を、タグ付けされた列として定義できます。各テーブルには、最大 64,993 のタグ付けされた列を定義できます。

参照している情報が最新であることを確認したり、他の Exchange Server 2007 ドキュメントを見つけたりするには、Exchange Server TechCenter を参照してください。