Grundlegendes zu TPS-Komponenten

Jedes Transaktionsverarbeitungssystem (TPS), das den Kernel Transaction Manager (KTM) und das Common Log File System (CLFS) verwendet, sollte die folgenden wichtigen Komponenten enthalten:

  • Ein Transaktions-Manager (KTM)

    KTM verfolgt den Status jeder Transaktion und koordiniert Wiederherstellungsvorgänge nach einem Systemabsturz.

  • Mindestens ein Ressourcen-Manager

    Ressourcen-Manager, die Sie bereitstellen, verwalten die Daten, die jeder Transaktion zugeordnet sind.

  • Mindestens ein CLFS-Protokollstream

    Der Transaktions-Manager und Ressourcen-Manager verwenden CLFS-Protokollstreams, um Informationen aufzuzeichnen, die zum Commit, Rollback oder Wiederherstellen einer Transaktion verwendet werden können.

  • Mindestens ein Transaktionsclient

    In der Regel kann jeder Transaktionsclient Ihres TPS eine Transaktion erstellen, Vorgänge für Daten im Kontext der Transaktion ausführen und dann entweder einen Commit- oder Rollbackvorgang für die Transaktion initiieren.

In diesem Thema wird ein einfacher TPS mit einem Ressourcen-Manager, einem komplexeren TPS mit mehreren Ressourcen-Managern und einigen anderen TPS-Szenarien vorgestellt.

Der Abschnitt Using KTM enthält ausführliche Informationen zur Verwendung von KTM zum Erstellen von TPS-Komponenten.

Einfache TPS

Ein einfacher TPS kann aus KTM, einem Ressourcen-Manager und CLFS bestehen. Transaktionsclients können über eine Vom Ressourcen-Manager bereitgestellte Schnittstelle mit dem Ressourcen-Manager kommunizieren.

Angenommen, Sie möchten ein Datenbankverwaltungssystem erstellen. Sie möchten, dass die Clients Ihres Systems auf die Datenbank zugreifen, indem Sie ein Handle für ein Datenbankobjekt öffnen, Lese- und Schreibvorgänge für das Objekt ausführen und dann das Objekthandle schließen.

Angenommen, Sie möchten, dass Sätze von Lese- und Schreibvorgängen atomar ausgeführt werden sollen, sodass andere Benutzer des Systems nur das Endergebnis sehen. Sie können dieses Ziel erreichen, indem Sie ein TPS entwerfen, mit dem Clients Datenbankvorgänge an eine Transaktion binden können.

Ihr System sollte einen Ressourcen-Manager enthalten, der die Daten in der Datenbank als Reaktion auf Lese- und Schreibanforderungen von Clients verwaltet. Dieser Ressourcen-Manager könnte eine API (Application Programming Interface) exportieren, die es Clients ermöglicht, eine Transaktion einer Reihe von Lese- und Schreibvorgängen zuzuordnen.

Wenn Ihr Ressourcen-Manager geladen wird, muss er sich bei KTM registrieren, indem er ZwCreateTransactionManager und ZwCreateResourceManager aufruft. Anschließend kann der Ressourcen-Manager an Transaktionen teilnehmen.

Möglicherweise soll Ihr Ressourcen-Manager eine Reihe von Funktionen unterstützen, die es Clients ermöglichen, Datenobjekte zu erstellen, daten zu lesen und zu schreiben, die den Datenobjekten zugeordnet sind, und die Datenobjekte zu schließen. Der folgende Pseudocode zeigt eine Beispielcodesequenz von einem Client.

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);

Bevor ein Client die CreateDataObject-Routine Ihres Ressourcen-Managers aufrufen kann, muss der Client ein Transaktionsobjekt erstellen, indem er die ZwCreateTransaction-Routine von KTM aufruft und den Bezeichner des Transaktionsobjekts durch Aufrufen von ZwQueryInformationTransaction abruft.

Wenn der Client die CreateDataObject-Routine Ihres Ressourcen-Managers aufruft, übergibt der Client den Bezeichner des Transaktionsobjekts an den Ressourcen-Manager. Der Ressourcen-Manager kann ZwOpenTransaction aufrufen, um ein Handle für das Transaktionsobjekt abzurufen. Anschließend kann er ZwCreateEnlistment aufrufen, um seine Teilnahme an der Transaktion zu registrieren.

An diesem Punkt kann der Client mit der Ausführung von Vorgängen für das Datenobjekt beginnen. Da der Client beim Erstellen des Datenobjekts einen Transaktionsbezeichner bereitgestellt hat, kann der Ressourcen-Manager der Transaktion alle Lese- und Schreibvorgänge zuweisen.

Ihr Ressourcen-Manager muss alle Ergebnisse von Datenvorgängen aufzeichnen, die der Client angibt, ohne die Ergebnisse dauerhaft zu machen. In der Regel verwendet der Ressourcen-Manager CLFS, um die Vorgangsergebnisse in einem Transaktionsprotokolldatenstrom aufzuzeichnen.

Wenn der Client den Ressourcen-Manager zum Ausführen von Transaktionsvorgängen aufgerufen hat, ruft er die ZwCommitTransaction-Routine von KTM auf. An diesem Punkt benachrichtigt KTM den Ressourcen-Manager, dass er den Betrieb dauerhaft machen soll. Der Ressourcen-Manager verschiebt dann die Vorgangsergebnisse aus dem Protokolldatenstrom auf das permanente Speichermedium der Daten. Schließlich ruft der Ressourcen-Manager ZwCommitComplete auf, um KTM darüber zu informieren, dass der Commitvorgang abgeschlossen ist.

Was geschieht, wenn Ihr Ressourcen-Manager einen Fehler für einen der Aufrufe von ReadData oder WriteData des Clients meldet? Der Client kann ZwRollbackTransaction aufrufen, um ein Rollback für die Transaktion auszuführen. Als Ergebnis dieses Aufrufs benachrichtigt KTM den Ressourcen-Manager, dass die Daten in ihren ursprünglichen Zustand wiederhergestellt werden sollen. Anschließend kann der Client entweder eine neue Transaktion für die gleichen Vorgänge erstellen oder nicht fortfahren.

Der folgende Pseudocode zeigt ein Beispiel für eine ausführlichere Sequenz der Transaktionsvorgänge eines Clients.

    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;

Was geschieht, wenn das System abstürzt, nachdem die Transaktion erstellt wurde, aber bevor ein Commit ausgeführt oder ein Rollback ausgeführt wird? Jedes Mal, wenn Ihr Ressourcen-Manager geladen wird, sollte er ZwRecoverTransactionManager und ZwRecoverResourceManager aufrufen. Der Aufruf von ZwRecoverTransactionManager bewirkt, dass KTM seinen Protokolldatenstrom öffnet und den Transaktionsverlauf liest. Der Aufruf von ZwRecoverResourceManager bewirkt, dass KTM den Ressourcen-Manager über alle eingetragenen Transaktionen benachrichtigt, die vor dem Absturz ausgeführt wurden und welche Transaktionen der Ressourcen-Manager daher wiederherstellen muss.

Wenn ein Transaktionsclient mit dem Namen ZwCommitTransaction für eine Transaktion vor dem Absturz und mit der Verarbeitung von Commitvorgängen für die Transaktion begonnen hat, muss der Ressourcen-Manager in der Lage sein, den Status der Transaktion auf den Punkt unmittelbar vor dem Absturz wiederherzustellen. Wenn der Client vor dem Absturz nicht bereit war, die Transaktion zu committen, kann der Ressourcen-Manager die Daten verwerfen und ein Rollback für die Transaktion ausführen.

Weitere Informationen zum Schreiben von Transaktionsclients finden Sie unter Erstellen eines Transaktionsclients.

Weitere Informationen zum Schreiben von Ressourcen-Managern finden Sie unter Erstellen einer Resource Manager.

Mehrere Ressourcen-Manager in einem TPS

Angenommen, Ihr TPS ermöglicht Clients das Ändern von Informationen in zwei separaten Datenbanken innerhalb einer einzelnen Transaktion, sodass die Transaktion nur erfolgreich ist, wenn die Änderungen beider Datenbanken erfolgreich sind.

In diesem Fall kann Ihr TPS über zwei Ressourcen-Manager verfügen, einen für jede Datenbank. Jeder Ressourcen-Manager kann eine API exportieren, die Clients für den Zugriff auf die Datenbank des Ressourcen-Managers verwenden können.

Der folgende Pseudocode zeigt, wie ein Client eine einzelne Transaktion erstellen kann, die Vorgänge für zwei Datenbanken enthält, die von zwei Ressourcen-Managern unterstützt werden.

In diesem Beispiel liest der Client Daten aus der ersten Datenbank und schreibt sie in die zweite Datenbank. Anschließend liest der Client Daten aus der zweiten Datenbank und schreibt sie in die erste Datenbank. (Der erste Ressourcen-Manager exportiert Funktionen, die mit Rm1 beginnen, und der zweite Ressourcen-Manager exportiert Funktionen, die mit Rm2 beginnen.)

    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;

Da der Client denselben Transaktionsbezeichner an beide Ressourcen-Manager übergibt, können beide Ressourcen-Manager ZwOpenTransaction und ZwCreateEnlistment aufrufen, um sich in der Transaktion zu eintragen. Wenn der Client schließlich ZwCommitTransactionaufruft, benachrichtigt KTM jeden Ressourcen-Manager, dass der Manager die Vorgänge dauerhaft machen soll, und jeder Ressourcen-Manager ruft ZwCommitComplete auf, wenn er abgeschlossen ist.

Andere TPS-Szenarien

KTM unterstützt andere TPS-Szenarien. In den folgenden Szenarien werden beispielsweise Komponenten beschrieben, die ein TPS enthalten kann:

  • Ein Ressourcen-Manager, der mehrere Datenbanken verwaltet.

    Mit der API des Ressourcen-Managers können Clients gleichzeitig mehr als eine Datenbank öffnen und darauf zugreifen, und der Client könnte Zugriffe auf mehrere Datenbanken in einer einzigen Transaktion kombinieren.

  • Ein Ressourcen-Manager mit einer API, die von Clients aufgerufen wird, und zusätzliche Ressourcen-Manager mit APIs, die der erste Ressourcen-Manager aufruft.

    Der Client kommuniziert nur mit dem ersten Ressourcen-Manager. Wenn dieser Ressourcen-Manager Anforderungen von einem Client verarbeitet, kann er bei Bedarf auf die zusätzlichen Ressourcenmanager zugreifen, um die Anforderungen des Clients zu verarbeiten. Beispielsweise verwaltet ein Ressourcen-Manager eine vom Client zugängliche Datenbank, die Sicherungs- oder Datenüberprüfungsvorgänge von einem zweiten Ressourcen-Manager erfordert, der für Clients nicht verfügbar ist.

  • Ein vorhandener Client und Ressourcen-Manager, der nicht KTM verwendet, integriert in einen zusätzlichen Satz von Ressourcen-Managern, die KTM verwenden.

    In diesem Fall müssen Sie in der Regel den vorhandenen Ressourcen-Manager so ändern, dass er zu einem überlegenen Transaktions-Manager wird, der mit KTM kommuniziert.