コミット操作の処理

コミット操作には、単一フェーズ コミットマルチフェーズ コミットの 2 種類があります。 単一フェーズ コミット操作は、リソース マネージャーが応答する必要がある 1 つの通知で構成され、複数フェーズのコミット操作には、準備手順に関する追加の通知が含まれています。

単一フェーズ コミット操作の方が実装が簡単です。 次のいずれかの特性を持つトランザクション処理システム (TPS) に適しています。

  • 単一のリソース マネージャー。

  • マルチ リソース マネージャーは、1 つを除きすべて読み取り専用であり、コミット操作には参加しません。

複数のリソース マネージャーがコミット操作に参加する場合、マルチ フェーズ コミット操作が必要です。

単一フェーズ コミット操作

TPS で単一フェーズ コミット操作をサポートする場合、1 つのリソース マネージャー (1 つだけ) が、その参加に関する TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT 通知を受け取るよう登録する必要があります。 他のすべてのリソース マネージャーは読み取り専用でなければなりません。

上位トランザクション マネージャーが入った TPS は、単一フェーズ コミットを使用できません。

リソース マネージャーが TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT 通知を受け取るよう登録されている場合、KTM はトランザクション クライアントが ZwCommitTransaction を呼び出すときに、この種類の通知を送信します。

リソース マネージャーは、トランザクションの TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT 通知を受け取ると、トランザクションをコミットするか、単一フェーズ コミットを拒否できます。

トランザクションをコミットするには、リソース マネージャーで以下の操作を行う必要があります。

  1. 非永続的キャッシュ (メモリ内ストレージ) に保持されているすべてのデータ (CLFS ログ ストリームCLFS マーシャリング領域など) をフラッシュします。

    リソース マネージャーは、キャッシュから永続ストレージ メディアにデータを移動する必要があります。 たとえば、CLFS を使用しているリソース マネージャーは ClfsFlushBuffers を呼び出すことができます。

  2. すべてのデータ変更を永続的かつパブリックにします (つまり、リソース マネージャーの範囲外で表示されます)。

  3. ZwCommitComplete を呼び出 します。

ZwCommitComplete を呼び出した後、リソース マネージャーは ZwClose を呼び出して、参加ハンドルを閉じる必要があります。

トランザクションの単一フェーズ コミット操作を拒否するため、リソース マネージャーは ZwSinglePhaseReject を呼び出すことができます。 リソース マネージャーが ZwSinglePhaseReject を呼び出した場合、KTM は直ちにコミット操作を単一フェーズからマルチフェーズに変更します。

他のリソース マネージャーが同じトランザクションに参加する場合、読み取り専用でなければなりません。 ただし、TRANSACTION_NOTIFY_RM_DISCONNECTED 通知を受け取るよう登録する必要があります。この通知は、単一フェーズのコミット操作を処理しているリソース マネージャーが、トランザクションをコミットまたはロールバックしたことを示さずに参加ハンドルを閉じた場合に受け取ります。

マルチフェーズ コミット操作

マルチフェーズ コミット操作は、以下のいずれかのイベントが発生したときに開始されます。

マルチフェーズ コミット操作は、3 つの順次フェーズ (事前準備準備コミット) で構成されています。

事前準備フェーズ

コミット操作の事前準備フェーズ (フェーズ 0 とも呼ばれます) は、KTM がすべてのリソース マネージャーに TRANSACTION_NOTIFY_PREPREPARE 通知を送信すると開始されます。 トランザクションの単一フェーズ コミット操作をサポートするリソース マネージャーがない場合、または上位トランザクション マネージャーが ZwPrePrepareEnlistment を呼び出した場合、KTM はこの通知を送信します。

各リソース マネージャーは、TRANSACTION_NOTIFY_PREPREPARE 通知を受け取ったら、以下の操作を行う必要があります。

  1. 非永続的キャッシュ (メモリ内ストレージ) に保持されているすべてのデータ (CLFS ログ ストリームCLFS マーシャリング領域など) をフラッシュします。

    リソース マネージャーは、キャッシュから永続ストレージ メディアにデータを移動する必要があります。 たとえば、CLFS を使用しているリソース マネージャーは ClfsFlushBuffers を呼び出すことができます。

  2. ZwPrePrepareComplete を呼び出します。

リソース マネージャーは、ZwPreprepareComplete を呼び出した後も、クライアント要求の受信と処理を続行できます。 ただし、リソース マネージャーは、すべてのデータ変更を、永続ストレージ メディアに直ちに書き込まれるキャッシュ パススルー操作として扱う必要があります。

リソース マネージャーは、TRANSACTION_NOTIFY_PREPREPARE 通知の処理時にエラーが発生した場合、ZwRollbackEnlistment を呼び出してトランザクションをロールバックする必要があります。

準備フェーズ

コミット操作の準備フェーズ (フェーズ 1 とも呼ばれます) は、KTM がすべてのリソース マネージャーに TRANSACTION_NOTIFY_PREPARE 通知を送信すると開始されます。 単一フェーズ コミットをサポートしているリソース マネージャーがない場合、または上位トランザクション マネージャーが ZwPrepareEnlistment を呼び出した場合、KTM は TRANSACTION_NOTIFY_PREPREPARE の後にこの通知を送信します。

各リソース マネージャーは、TRANSACTION_NOTIFY_PREPARE 通知を受け取ったら、以下の操作を行う必要があります。

  1. クライアント要求の処理を停止し、クライアントの後続の要求をクライアント エラーとして報告します。

  2. すべてのデータが永続ストレージに移動されたことを確認します。

  3. ZwPrepareComplete を呼び出します。

リソース マネージャーは、TRANSACTION_NOTIFY_PREPARE 通知の処理時にエラーが発生した場合、ZwRollbackEnlistment を呼び出してトランザクションをロールバックする必要があります。 ただし、リソース マネージャーは、ZwPrepareComplete を呼び出した後にトランザクションをロールバックすることができません。

コミット フェーズ

コミット操作のコミット フェーズ (フェーズ 2 とも呼ばれます) は、KTM がすべてのリソース マネージャーに TRANSACTION_NOTIFY_COMMIT 通知を送信すると開始されます。 単一フェーズ コミットをサポートしているリソース マネージャーがない場合、または上位トランザクション マネージャーが ZwPrepareEnlistment を呼び出した場合、KTM は TRANSACTION_NOTIFY_PREPARE の後にこの通知を送信します。

各リソース マネージャーは、TRANSACTION_NOTIFY_COMMIT 通知を受け取ったら、以下の操作を行う必要があります。

  1. すべてのデータ変更を永続的かつパブリックにします (つまり、他のトランザクションに表示されます)。

    通常、リソース マネージャーは、トランザクションの保存済みデータをログ ストリームからデータベースのパブリック永続ストレージにコピーすることにより、変更を永続的およびパブリックにします。 ログ ストリームの使用方法について詳しくは、「KTM でのログ ストリームの使用」をご覧ください。

  2. ZwCommitComplete を呼び出 します。

リソース マネージャーは、ZwCommitComplete を呼び出した後、ZwClose を呼び出して参加ハンドルを閉じる必要があります。

リソース マネージャーが TRANSACTION_NOTIFY_COMMIT 通知の処理しているときにエラーが発生した場合、それ自体をシャットダウンする必要があります。 オペレーティング システムが次にリソース マネージャーを再読み込みするとき、リソース マネージャーの回復プロセスは、エラーが発生する前に正常であることがわかっていた状態にトランザクションを復元する必要があります。