Probleme mit TransactionScope und Oracle
Wir haben einen C # 3.5-Client geschrieben, der über ODP.NET mit einer Oracle-Datenbank (11g) kommuniziert.
Diese Anwendung verfügt über einen Stapelverarbeitungsprozess, in dem eine Task mit langer Laufzeit ausgeführt wird, die innerhalb eines TransactionScope verschiedene Aufrufe an die Datenbank ausführt.
n unserer Entwicklungsumgebung funktioniert alles einwandfrei, aber in der UAT-Umgebung eines unserer Clients (der viele Daten hat) treten zwei abwechselnde Fehler (manchmal der eine, manchmal der andere ...) auf:
Kann nicht in eine verteilte Transaktion aufgenommen werden Die Transaktion wurde abgebrochen. (innere Ausnahme: Transaktions-Timeout)Wir verwenden derzeit eine Zeitüberschreitung vonEines Tage für die Transaktion (zu Testzwecken).
Das Ausführen dieses Vorgangs in der UAT-Umgebung führt nach ca. 10 Minuten mit einer der oben genannten Ausnahmen, also nicht in der Nähe des Timeout-Werts.
Hier ist ein Ausschnitt aus dem Stacktrace für den zweiten Fehler:
at System.Transactions.TransactionStatePromotedAborted.CreateAbortingClone(InternalTransaction tx)
at System.Transactions.DependentTransaction..ctor(IsolationLevel isoLevel, InternalTransaction internalTransaction, Boolean blocking)
at System.Transactions.Transaction.DependentClone(DependentCloneOption cloneOption)
at System.Transactions.TransactionScope.SetCurrent(Transaction newCurrent)
at System.Transactions.TransactionScope.PushScope()
at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption)
at System.Transactions.TransactionScope..ctor()
at Application.Domain.DataAccess.Oracle.EntityDaoBase`2.SaveItem(TEntity item, EntityReference`1 user)
Der Prozess versucht, ein Element innerhalb des Transaktionsbereichs in der Datenbank zu speichern. Die Stapelverfolgung zeigt jedoch, dass der Konstruktor für die TransactionScope-Klasse getroffen wurde, dh, er erstellt einen neuen TransactionScope.
Bin ich richtig so weit?
Weil ich nicht viel über die Funktionsweise von TransactionScope weiß, aber es scheint, als würde beim Aufrufen einer Methode innerhalb des Gültigkeitsbereichs eine neue Transaktion erstellt (vorausgesetzt, sie erbt von der Umgebungstransaktion).
Kann es sein, dass diese neue Transaktion, wenn ich recht habe, nicht das richtige Timeout (sondern das Standard-Timeout) erbt, sodass eine verschachtelte Transaktion diese Timeout-Ausnahme verursacht?
Wenn nicht, irgendwelche Gedanken darüber, was es möglicherweise sein kann? Nebenbei bemerkt, es sind keine verschachtelten Transaktionen in den Methoden definiert, die in der Umgebungstransaktion aufgerufen werden.
Jede Hilfe wäre sehr dankbar!
Edit 1:
Vereinfachtes Code-Snippet der Funktion:
public void SomeLengthyBatchProcess()
{
using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
{
foreach (var item in Items)
{
SaveItemToDB(item);
}
transaction.Complete();
}
}
public void SaveItemToDB(object item)
{
using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))
{
// Performing data persistency here
transaction.Complete();
}
}
Edit 2:
Okay, also wie sich herausstellt, gibt es ist Eine verschachtelte Transaktion, die in der Methode 'SaveItemToDB' ausgeführt wird. Nachdem ein Kollege den Code durchgearbeitet hatte, stellte ich fest, dass ein eigener TransactionScope definiert ist, jedoch ohne Optionen und Zeitlimit.
Nachdem ich diese Methode so geändert habe, dass sie hinsichtlich der Zeitüberschreitung dieselben Parameter aufweist, habe ich den Code erneut auf dem Server des Kunden ausgeführt und immer noch kein Glück gehabt (erneut hat die Transaktion den Fehler mit der Zeitüberschreitung abgebrochen).
So sind meine Fragen jetzt wie folgt:
Müssen Timeout-Werte für verschachtelte Transaktionen definiert werden oder erben sie diese von der Umgebungstransaktion?Wie ist es möglich, dass eine Zeitüberschreitungsausnahme auftritt, wenn die Zeitüberschreitungseinstellung (vermutlich abgesehen von den mir nicht bekannten internen Abläufen) für alle Transaktionsbereiche gleich ist und ein Zeitüberschreitungswert von 1 Tag definiert ist, für den die Ausnahme auftritt nach ca. 10 MinutenIst es möglich zu verhindern, dass Oracle eine verteilte Transaktion für Transaktionen erstellt, bei denen die Verbindungszeichenfolge identisch ist?Kann es sein, dass der hinzugefügte Overhead einer verteilten Transaktion Ausnahmen wie die abgebrochene Transaktion verursacht?Ich habe das Code-Snippet aktualisiert, damit es die Situation besser widerspiegelt.
(Übrigens: Die zweite, verschachtelte Transaktion ist erforderlich, da die DAL auch einige untergeordnete Elemente, falls vorhanden, separat speichert und das gesamte Element natürlich zurückgesetzt werden sollte, wenn beim Speichern der untergeordneten Elemente etwas schief geht.)
Hoffentlich wird es mit diesem Zusatz einfacher, etwas Licht in dieses Problem zu bringen!