次の方法で共有


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;

トランザクションが作成された後、コミットまたはロールバックされる前にシステムがクラッシュした場合はどうなりますか? リソース マネージャーが読み込まれるたびに、 ZwRecoverTransactionManagerZwRecoverResourceManager を呼び出す必要があります。 ZwRecoverTransactionManager を呼び出すと、KTM はログ ストリームを開き、トランザクション履歴を読み取ります。 ZwRecoverResourceManager を呼び出すと、KTM は、クラッシュ前に進行中であったすべての参加済みトランザクションと、リソース マネージャーが回復する必要があるトランザクションをリソース マネージャーに通知します。

クラッシュ前にトランザクションに 対して ZwCommitTransaction というトランザクション クライアントが呼び出され、トランザクションのコミット操作の処理を開始した場合、リソース マネージャーは、クラッシュの直前の時点にトランザクションの状態を復元できる必要があります。 クライアントがクラッシュ前にトランザクションをコミットする準備ができていない場合、リソース マネージャーはデータを破棄し、トランザクションをロールバックできます。

トランザクション クライアントの作成方法の詳細については、「 トランザクション クライアントの作成」を参照してください。

リソース マネージャーの作成方法の詳細については、「リソース マネージャー の作成」を参照してください。

TPS 内の複数のリソース マネージャー

次に、TPS を使用して、クライアントが 1 つのトランザクション内の 2 つの個別のデータベース内の情報を変更し、両方のデータベースの変更が成功した場合にのみトランザクションが成功するとします。

この場合、TPS には、データベースごとに 1 つずつ、2 つのリソース マネージャーを使用できます。 各リソース マネージャーは、クライアントがリソース マネージャーのデータベースにアクセスするために使用できる API をエクスポートできます。

次の擬似コードは、2 つのリソース マネージャーがサポートする 2 つのデータベースに対する操作を含む単一のトランザクションをクライアントが作成する方法を示しています。

この例では、クライアントは最初のデータベースからデータを読み取り、2 番目のデータベースに書き込みます。 次に、クライアントは 2 番目のデータベースからデータを読み取り、最初のデータベースに書き込みます。 (最初のリソース マネージャーは 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;

クライアントは両方のリソース マネージャーに同じトランザクション識別子を渡すので、両方のリソース マネージャーが ZwOpenTransactionZwCreateEnlistment を呼び出してトランザクションに参加させることができます。 クライアントが最終的に ZwCommitTransaction を呼び出すと、KTM は、マネージャーが操作を永続的にする必要があることを各リソース マネージャーに 通知 し、各リソース マネージャーは終了時に ZwCommitComplete を 呼び出します。

その他の TPS シナリオ

KTM では、他の TPS シナリオがサポートされています。 たとえば、次のシナリオでは、TPS に含まれるコンポーネントについて説明します。

  • 複数のデータベースを管理する 1 つのリソース マネージャー。

    リソース マネージャーの API を使用すると、クライアントは一度に複数のデータベースを開いてアクセスでき、クライアントは 1 つのトランザクションで複数のデータベースへのアクセスを組み合わせることができます。

  • クライアントが呼び出す API を持つ 1 つのリソース マネージャーと、最初のリソース マネージャーが呼び出す API を持つ他のリソース マネージャー。

    クライアントは、最初のリソース マネージャーとのみ通信します。 そのリソース マネージャーは、クライアントからの要求を処理するときに、必要に応じて追加のリソース マネージャーにアクセスして、クライアントの要求を処理できます。 たとえば、リソース マネージャーは、クライアントがアクセスできない 2 つ目のリソース マネージャーからのバックアップ操作またはデータ検証操作を必要とする、クライアントからアクセス可能なデータベースを管理します。

  • KTM を使用しない既存のクライアントおよびリソース マネージャーが、KTM を使用する追加のリソース マネージャーのセットと統合されています。

    この場合、通常は、KTM と通信する 優れたトランザクション マネージャー になるように、既存のリソース マネージャーを変更する必要があります。