TPS コンポーネントの概要
カーネル トランザクション マネージャー (KTM) と共通ログ ファイル システム (CLFS) を使用するトランザクション処理システム (TPS) には、次の重要なコンポーネントが含まれている必要があります。
トランザクション マネージャー (KTM)
KTM は、各トランザクションの状態を追跡し、システム クラッシュ後の回復操作を調整します。
1 つ以上の リソース マネージャー
指定したリソース マネージャーは、各トランザクションに関連付けられているデータを管理します。
1 つ以上の CLFS ログ ストリーム
トランザクション マネージャーとリソース マネージャーは、CLFS ログ ストリームを使用して、トランザクションのコミット、ロールバック、または回復に使用できる情報を記録します。
1 つ以上の トランザクション クライアント
通常、TPS の各トランザクション クライアントは、トランザクションを作成し、トランザクションのコンテキスト内でデータに対する操作を実行してから、トランザクションのコミット操作またはロールバック操作を開始できます。
このトピックでは、リソース マネージャーが 1 つの単純な TPS、複数のリソース マネージャーを含むより複雑な TPS、およびその他の TPS シナリオについて説明します。
「KTM の 使用」セクションでは、KTM を使用して TPS コンポーネントを作成する方法について詳しく説明します。
単純な TPS
単純な TPS は、KTM、1 つのリソース マネージャー、および CLFS で構成される場合があります。 トランザクション クライアントは、リソース マネージャーが提供するインターフェイスによってリソース マネージャーと通信できます。
たとえば、データベース管理システムを作成するとします。 データベース オブジェクトへのハンドルを開き、オブジェクトに対して読み取り操作と書き込み操作を実行した後、オブジェクト ハンドルを閉じます。こうして、システムのクライアントがデータベースにアクセスできるようにします。
次に、システムの他のユーザーが最終的な結果のみを表示できるように、読み取り操作と書き込み操作のセットをアトミックに実行するとします。 この目標を達成するには、クライアントがデータベース操作のセットをトランザクションにバインドできるようにする TPS を設計します。
システムに、クライアントからの読み取りと書き込みの要求に応答して、データベース内のデータを管理するリソース マネージャーを含める必要があります。 このリソース マネージャーは、クライアントがトランザクションを一連の読み取りおよび書き込み操作に関連付けることができるアプリケーション プログラミング インターフェイス (API) をエクスポートできます。
リソース マネージャーが読み込まれるときは、ZwCreateTransactionManager と ZwCreateResourceManager を呼び出して、KTM に自身を登録する必要があります。 その後、リソース マネージャーはトランザクションに参加できます。
リソース マネージャーで、クライアントがデータ オブジェクトを作成し、データ オブジェクトに関連付けられたデータの読み取りと書き込みを行い、データ オブジェクトを閉じることができる一連の関数をサポートする必要があるかもしれません。 次の擬似コードは、クライアントからのコード シーケンスの例を示しています。
CreateDataObject (IN TransactionID, OUT DataHandle);
ReadData (IN DataHandle, OUT Data);
WriteData (IN DataHandle, IN Data);
WriteData (IN DataHandle, IN Data);
WriteData (IN DataHandle, IN Data);
CloseDataObject (IN DataHandle);
クライアントは、リソース マネージャーの CreateDataObject ルーチンを呼び出す前に、KTM の ZwCreateTransaction ルーチンを呼び出してトランザクション オブジェクトを作成し、ZwQueryInformationTransaction を呼び出してトランザクション オブジェクトの識別子を取得する必要があります。
クライアントがリソース マネージャーの CreateDataObject ルーチンを呼び出すと、クライアントはトランザクション オブジェクトの識別子をリソース マネージャーに渡します。 リソース マネージャーは、ZwOpenTransaction を呼び出してトランザクション オブジェクトのハンドルを取得し、ZwCreateEnlistment を呼び出してトランザクションへの参加を登録できます。
この時点で、クライアントはデータ オブジェクトに対する操作の実行を開始できます。 クライアントはデータ オブジェクトの作成時にトランザクション識別子を指定したため、リソース マネージャーはすべての読み取り操作と書き込み操作をトランザクションに割り当てることができます。
リソース マネージャーは、結果を永続化することなく、クライアントが指定したデータ操作のすべての結果を記録する必要があります。 通常、リソース マネージャーは CLFS を使用して、操作結果をトランザクション ログ ストリームに記録します。
クライアントは、トランザクション操作を実行するためにリソース マネージャーの呼び出しを完了すると、KTM の ZwCommitTransaction ルーチンを呼び出します。 この時点で、KTM は、操作を永続的にする必要があることをリソース マネージャーに通知します。 その後、リソース マネージャーは、操作の結果をログ ストリームからデータの永続的なストレージ メディアに移動します。 最後に、リソース マネージャーは ZwCommitComplete を呼び出して、コミット操作が完了したことを KTM に通知します。
リソース マネージャーが、ReadData または WriteData に対するクライアントの呼び出しの 1 つに対してエラーを報告した場合はどうなりますか? クライアントは、ZwRollbackTransaction を呼び出してトランザクションをロールバックできます。 その呼び出しの結果として、KTM は、元の状態にデータを復元する必要があることをリソース マネージャーに通知します。 その後、クライアントは同じ操作に対して新しいトランザクションを作成するか、続行しないことを選択できます。
次の擬似コードは、クライアントのトランザクション操作のより詳細なシーケンスの例を示しています。
ZwCreateTransaction (&TransactionHandle, ...);
ZwQueryInformationTransaction (TransactionHandle, ...);
CreateDataObject (TransactionID, &DataHandle);
Status = ReadData (DataHandle, &Data1);
if (Status == Error) goto ErrorRollback;
Status = WriteData (DataHandle, Data2);
if (Status == Error) goto ErrorRollback;
Status = WriteData (DataHandle, Data3);
if (Status == Error) goto ErrorRollback;
Status = WriteData (DataHandle, Data4);
if (Status == Error) goto ErrorRollback;
ZwCommitTransaction (TransactionHandle, ...);
goto Leave;
ErrorRollback:
ZwRollbackTransaction (TransactionHandle, ...);
Leave:
ZwClose (TransactionHandle);
return;
トランザクションが作成された後、コミットまたはロールバックされる前にシステムがクラッシュした場合はどうなりますか? リソース マネージャーが読み込まれるたびに、ZwRecoverTransactionManager と ZwRecoverResourceManager を呼び出す必要があります。 ZwRecoverTransactionManager を呼び出すと、KTM はログ ストリームを開き、トランザクション履歴を読み取ります。 ZwRecoverResourceManager を呼び出すと、KTM は、クラッシュ前に進行中であったすべての参加トランザクションと、リソース マネージャーが回復する必要があるトランザクションをリソース マネージャーに通知します。
クラッシュ前にトランザクションに対して ZwCommitTransaction というトランザクション クライアントが呼び出され、トランザクションのコミット操作の処理を開始した場合、リソース マネージャーは、そのトランザクションの状態をクラッシュ直前の時点に復元できなければなりません。 クライアントがクラッシュ前にトランザクションをコミットする準備ができていない場合、リソース マネージャーはデータを破棄し、トランザクションをロールバックできます。
トランザクション クライアントの書き込み方法の詳細については、「トランザクション クライアントの作成」を参照してください。
リソース マネージャーの書き込み方法の詳細については、「リソース マネージャーの作成」を参照してください。
TPS 内の複数のリソース マネージャー
次に、TPS を使用して、クライアントが 1 つのトランザクション内の 2 つの個別のデータベース内の情報を変更し、両方のデータベースの変更が成功した場合にのみトランザクションが成功するとします。
この場合、TPS には、データベースごとに 1 つずつ、2 つのリソース マネージャーを含めることができます。 各リソース マネージャーは、クライアントがリソース マネージャーのデータベースにアクセスするために使用できる API をエクスポートできます。
次の擬似コードは、単一のトランザクションをクライアントが作成する方法を示しています。そのトランザクションは、2 つのリソース マネージャーがサポートする 2 つのデータベースに対する操作を含みます。
この例では、クライアントは最初のデータベースからデータを読み取り、2 番目のデータベースに書き込みます。 次に、クライアントは 2 番目のデータベースからデータを読み取り、1 番目のデータベースに書き込みます。 (最初のリソース マネージャーは、Rm1 で始まる関数をエクスポートし、2 番目のリソース マネージャーは、Rm2 で始まる関数をエクスポートします。)
ZwCreateTransaction (&TransactionHandle, ...);
ZwQueryInformationTransaction (TransactionHandle, ...);
Rm1CreateDataObject (TransactionID, &Rm1DataHandle);
Rm2CreateDataObject (TransactionID, &Rm2DataHandle);
Status = Rm1ReadData (Rm1DataHandle, &Rm1Data);
if (Status == Error) goto ErrorRollback;
Status = Rm2WriteData (Rm2DataHandle, Rm1Data);
if (Status == Error) goto ErrorRollback;
Status = Rm2ReadData (Rm2DataHandle, &Rm2Data);
if (Status == Error) goto ErrorRollback;
Status = Rm1WriteData (Rm1DataHandle, Rm2Data);
if (Status == Error) goto ErrorRollback;
ZwCommitTransaction (TransactionHandle, ...);
goto Leave;
ErrorRollback:
ZwRollbackTransaction (TransactionHandle, ...);
Leave:
ZwClose (TransactionHandle);
return;
クライアントは両方のリソース マネージャーに同じトランザクション識別子を渡すので、両方のリソース マネージャーが ZwOpenTransaction と ZwCreateEnlistment を呼び出して、トランザクションに参加させることができます。 クライアントが最終的に ZwCommitTransaction を呼び出すと、KTM は、マネージャーが操作を永続的にする必要があることを各リソース マネージャーに通知し、各リソース マネージャーは操作が終了すると ZwCommitComplete を呼び出します。
その他の TPS シナリオ
KTM では、他の TPS シナリオがサポートされています。 たとえば、次のシナリオでは、TPS に含まれるコンポーネントについて説明します。
複数のデータベースを管理する 1 つのリソース マネージャー。
リソース マネージャーの API を使用すると、クライアントは一度に複数のデータベースを開いてアクセスでき、クライアントは複数のデータベースへのアクセスを 1 つのトランザクションにまとめることができます。
クライアントが呼び出す API を持つ 1 つのリソース マネージャーと、最初のリソース マネージャーが呼び出す API を持つ追加のリソース マネージャー。
クライアントは、最初のリソース マネージャーとのみ通信します。 そのリソース マネージャーは、クライアントからの要求を処理するときに、必要に応じて追加のリソース マネージャーにアクセスして、クライアントの要求を処理できます。 たとえば、リソース マネージャーは、クライアントからアクセス可能なデータベースを管理します。これはクライアントが使用できない 2 番目のリソース マネージャーからのバックアップ操作またはデータ検証操作を必要とする場合です。
KTM を使用しない既存のクライアントとリソース マネージャーは、KTM を使用するリソース マネージャーの追加セットと統合されます。
この場合、通常は、KTM と通信する上位のトランザクション マネージャーになるように 、既存のリソース マネージャー を変更する必要があります。