Ist es ein korrektes Verhalten von Transaktionen?

9

Ich habe drei Transaktionsdienste, die innerhalb einer Transaktionsgrenze ausgeführt werden (stratTransaction oder begin transaction). Alle drei Dienste verwenden jeweils unterschiedliche Verbindungen (No_Transaction, Local_Transaction und XA_Transaction) für ihre Verarbeitung. Jetzt möchte ich wissen, wenn ich eine Transaktion (mit javax.transaction.TransactionManager) starten und diese drei Dienste innerhalb der Transaktionsgrenze ausführen, kann ich sehen, dass der Dienst, der NO und LOCAL Transaktionen verwendet, Daten in die Tabellen einfügen kann. Jetzt füge ich mehr Daten als die Tabellenbeschränkungen in eine Spalte ein, indem ich das Service-XA verwende (und ich weiß, dass es scheitern soll), und rufe das Commit auf (und eine Rollback-Prozedur, falls es Fehler gibt). Jetzt habe ich Daten in Tabellen von NO und lokalen Verbindungstabellen, während XA-Verbindungstabelle keine Daten haben. Jetzt:

Ich möchte wissen, dass, wenn die Transaktion an einem Punkt fehlgeschlagen ist, alle Daten aus allen Tabellen zurückgesetzt werden sollen oder nur die Daten des XA-Dienstes zurückgesetzt werden sollen.

Ich wollte auch wissen: 'Transaktion', wie ich weiß, ist ein Verfahren, Daten atomar zu übertragen. Warum also die Verbindungserstellung das Definieren des Transaktionstyps umfasst, der durch die Verbindung ausgeführt werden kann, ist dies nicht eine Eigenschaft von Transaktionen?

Ich möchte auch wissen, warum wir den Transaktionstyp in den Verbindungseigenschaften definieren müssen. Stattdessen müssen wir den Transaktionstyp definieren, wenn wir eine Transaktion starten und der Transaktionsmanager die angegebene Art von Transaktionen ausführen muss.

Vielen Dank im Voraus.

    
0o'-Varun-'o0 18.12.2012, 07:06
quelle

2 Antworten

4

Beginnen wir mit dem einfachsten Transaktionsmodus und erhöhen die Komplexität.

Keine Transaktion

Eine 'no transaction' Verbindung ist eine solche, die Daten wie das Versenden von E-Mails nicht "festschreibt" oder "zurücksetzt". Sobald Sie das Nachrichtenobjekt an den E-Mail-Server übergeben haben, wird es an den Empfänger gesendet, und die Nachricht wird nicht mehr zurückgesendet. Es ist fast so, als ob jeder Anruf zu dem Zeitpunkt, zu dem der Anruf zurückkehrt, ausgeführt wird. Beispiele für diese Art von Verbindung sind Verbindungen zu SMTP, SMS-Gateways, Druckern usw.

Ich glaube, dass Sie eine Datenbankverbindung auf diese Weise verwenden können, wenn Sie das automatische Commit aktiviert haben, aber es stellt sich die Frage, warum Sie überhaupt eine vollständige ACID-Datenbank haben ...

'normale' Transaktionen

Die normale Verbindung, z. B. zu einer SQL-Datenbank, kann eine Reihe von Statusänderungsbefehlen in einem internen Puffer speichern. Wenn alles erledigt ist und alles OK erscheint, wird der gesamte Puffer der Änderungen in den Datenspeicher geschrieben und andere Verbindungen können die Änderungen sehen. Wenn etwas schief geht, vor oder sogar während des Commits, kann der gesamte Satz von Änderungen verworfen werden (zurückgesetzt).

Eine kritische Einschränkung dieser Art von Verbindung ist der Umfang des Puffers - der Puffer ist Teil der Verbindung selbst. Mit anderen Worten, nur über die Verbindung können Sie in den Puffer schreiben.

Eine wichtige Aufgabe des Anwendungsservers ist es, diese Verbindungen zu verwalten. Wenn Sie den Verbindungspool bitten, Ihnen die Verbindung zu geben, erhalten Sie auf magische Weise jedes Mal dieselbe Verbindung (innerhalb einer einzigen Transaktion). Dies gilt auch dann, wenn ein EJB einen anderen aufruft oder wenn ein EJB einen Ressourcenadapter aufruft (vorausgesetzt, Sie verwenden die Semantik REQUIRES_TRANSACTION. Sie können dies mit REQUIRES_NEW überschreiben). Dieses Verhalten bedeutet, dass eine Webanforderung mehrere EJB-Aufrufe ausführen kann, von denen jeder mit mehreren Entity-Beans interagieren kann und die gesamte Datenbearbeitung in einer einzigen Verbindung mit einem einzelnen internen Puffer erfolgt. Es wird alles zusammen oder zusammen rückgängig gemacht werden.

Transaktionen mit mehreren Verbindungen

Das ist großartig, wenn Sie eine einzige Datenbank haben - aber (per Definition) benötigen Sie separate Verbindungen, wenn Sie mit separaten Datenbankinstanzen sprechen (z. B. auf verschiedenen Rechnern). Was passiert dann? Ihre EJB-Transaktion endet mit mehreren Verbindungen - jede Verbindung zu einer eindeutigen Datenbank. Dies scheint gut zu funktionieren, außer in einer Situation:

  • Sie haben Verbindung A zu Datenbank A und Verbindung B zu Datenbank B
  • Sie führen DML-Anweisungen auf A und B
  • aus
  • Sie übernehmen die EJB-Verbindung. Der Anwendungsserver jetzt:
    1. Übernimmt Verbindung A - Erfolg
    2. Commits Verbindung B - fehlgeschlagen (z. B. Einschränkung fehlschlägt) und Verbindung B rollt zurück

Dies ist ein Desaster - Sie haben die Transaktion in Datenbank A ausgeführt, und dies kann jetzt nicht rückgängig gemacht werden. Die Transaktion (und das gesamte EJB) wird jedoch auf Datenbank B zurückgesetzt.

(Interessanterweise ist Ihr Beispiel fast identisch - Sie haben Daten, die für die keine Transaktion und normale Transaktion festgeschrieben sind, aber nicht für die XA-Transaktion - die letzte der drei Verbindungen)

XA-Transaktionen

Hier kommt XA ins Spiel. Es bietet Logik zum Koordinieren von Transaktionen, die gegen verschiedene Datenquellen gebunden sind und simuliert eine einzelne Transaktion über mehrere Datenquellen. XA verpflichtet sich zu einem "Zwei-Phasen-Commit", das von einem Transaktionskoordinator verwaltet wird, der eine Anzahl von XA-Verbindungen verwaltet, die in die XA-Transaktion einbezogen sind. Der Koordinator

  1. Sendet über die XA-Verbindung eine Nachricht an jede Datenquelle, um festzustellen, ob die Transaktion festgeschrieben werden kann: Alle Beschränkungs- und Datenbanklogik wird bis zu dem Punkt unmittelbar vor einem endgültigen Festschreiben ausgeführt. Wenn eine Datenbank einen Fehler meldet, setzt der XA-Koordinator die gesamte Transaktion zurück. Phase 1 ist, wo fast die gesamte Transaktionsarbeit durchgeführt wird und so vergleichsweise lange dauert
  2. Wenn jede Datenbank gemeldet hat, dass die Transaktion festgeschrieben werden kann, sendet der Koordinator eine Nachricht an jede Datenbank, um die Transaktion zu bestätigen. Das passiert sehr schnell.

Beachten Sie, dass das zweiphasige Commit fehlschlagen kann , wenn in Phase 2 etwas schief läuft (z. B. ein Teil des Netzwerks stürzt ab oder eine der Datenbanken wird zwischen Phase 1 und Phase 2 ausgeschaltet) / p>

Da sich eine XA-Verbindung anders als eine normale Verbindung verhält, benötigt sie normalerweise ein anderes ConnectionFactory-Objekt, das verschiedene Objektinstanzen instanziiert als eine Nicht-XA-ConnectionFactory. Darüber hinaus benötigt die XA ConnectionFactory Konfigurationsparameter für den XA-Transaktionskoordinator, z. B. XA-Transaktionstimeouts, die zusätzlich zu den normalen Transaktionseigenschaften hinzugefügt werden.

Eine weitere Einschränkung: Nur Verbindungen, die von einer XA ConnectionFactory erstellt wurden, können einer XA-Transaktion und dem zugehörigen zweiphasigen Commit beitreten. Sie können sowohl XA- als auch Nicht-XA-Verbindungen an einer einzelnen Application Server-Transaktion teilnehmen, aber dann kann die gesamte Transaktion nicht zuverlässig als eine einzelne Transaktion (wie oben) festgeschrieben / zurückgesetzt werden.

Spezifische Antworten

  

Ich möchte wissen, dass es, wenn die Transaktion an einem Punkt fehlgeschlagen ist, alle Daten aus allen Tabellen rollback oder nur Daten von XA Service nur Rollbacks soll?

Wenn die Transaktion fehlschlägt, bevor der Anwendungsserver einen Commit versucht (z. B. erhält Ihr EJB eine NPE oder Sie führen einen absichtlichen Rollback durch), erhält jede Verbindung einen Rollback, und alles sollte wie erwartet sein.

Wenn jedoch die Transaktion in der Festschreibungslogik fehlschlägt (z. B. eine Datenbankeinschränkung), versucht der Transaktionsmanager, alles zurückzurollen; Dies kann nicht passieren, wenn eine Nicht-XA-Verbindung bereits festgeschrieben wurde.

  

Ich wollte auch wissen: 'Transaktion', wie ich weiß, ist ein Verfahren, Daten atomar zu übertragen. Warum also die Verbindungserstellung das Definieren des Transaktionstyps umfasst, der durch die Verbindung ausgeführt werden kann, ist dies nicht eine Eigenschaft von Transaktionen?

Die XA-Verbindung verwendet eine andere Bibliothek und ein anderes Protokoll als die normale Verbindung, da die Verbindung selbst mit dem XA-Transaktionskoordinator kommunizieren muss. Normale Verbindungen tun dies nicht.

  

Ich möchte auch wissen, warum wir Transaktionstyp in Verbindungseigenschaften definieren müssen, stattdessen müssen wir den Typ der Transaktion definieren, wenn wir eine Transaktion starten, und dieser Transaktionsmanager muss die angegebene Art von Transaktionen ausführen.

Da die XA-Verbindung anderen Code verwendet, muss der Verbindungspool im Vergleich zur normalen Verbindung eine andere Klasse laden. Aus diesem Grund unterscheiden sich die Eigenschaften des Verbindungspools (nicht der Verbindung).

    
Andrew Alcock 02.01.2013, 05:46
quelle
0

Ja, wenn eine Transaktion ihren Commit-Eintrag nicht in die Protokolldatei schreiben konnte, wird sie vollständig zurückgesetzt (Atomic-Eigenschaft von trxn).

Trxn ist eine atomare Einheit der Datenbankverarbeitung. Was auch immer Sie in der Datenbank mit txn ausführen, diese Aktion wird atomar sein. Standardmäßig ist die Transaktion vom Autocommit-Typ. Wenn Sie jedoch Ihren eigenen Code für die Angabe des Startpunkts und des Festschreibungspunkts einer TXN verwenden, ist dieser explizit (http://msdn.microsoft.com/en-us/library/ms172353.aspx)

    
Arpit 01.01.2013 17:56
quelle