2009-11-18 5 views
6

Ich beginne gerade mit der Verwendung von TransactionScope zu arbeiten, ich finde, dass es immer unerwartete Dinge gibt, die ich brauche, die ewig dauern, um zu debuggen.Häufige Probleme bei der Verwendung von TransactionScope und MS DTC

Ich denke, dass eine konsolidierte Liste von diesen wäre großartig für diese "seltsame Fehler" Umstände, plus unser Wissen über Ungereimtheiten in der Plattform zu erweitern.

Einiger Kontext auf, wie ich Transaktionstive werden werde mit:

  • Webapplikation
  • mehr Web-Server, Anwendungsserver und SQL Server
  • Transaktionen Datenbanktransaktionen werden in erster Linie, aber einige werden erhöht, um in MSMQ zu schreiben.

Antwort

3

2 Dinge aus der Spitze von meinem Kopf:

  • Transaktionen erhoben werden, wenn Sie mehr als ein Verbindungsobjekt in dem gleichen Bereich zu verwenden, auch wenn die Verbindungen die gleiche Connection haben (dies ist fest in SQL 2008). Lesen Sie mehr in this thread und dbconnectionscope löst dieses Problem auf SQL 2005
  • msdtc Instanzen müssen in der Lage sein, sich zu sehen und müssen ihre Sicherheit richtig eingerichtet haben http://support.microsoft.com/kb/899191 (erlauben inbound und outbound, benötigen keine gegenseitige Authentifizierung in der Regel ist die sicherste Wette). Verwenden Sie DTCPing zu Verbindungsproblemen zwischen dtc Instanzen zu beheben, wie hier erklärt: http://support.microsoft.com/kb/306843

Sie Transaktionen wollen so viel wie möglich leicht sein, stellt dtc eine Menge Aufwand. Sie möchten auch, dass Transaktionen so kurz wie möglich sind. Führen Sie sie daher nur auf den Anwendungsservern und nicht auf dem Webserver ein. Machen Sie den Sprung über das Netzwerk zwischen den Anwendungsservern und der Datenbank so klein wie möglich und so schnell wie möglich, senden Sie Netzwerkverkehr zwischen Web- und App-Server über eine andere Verbindung als zwischen App-Server und db, und machen Sie den letzten Schrei schnell lächerlich kurze Verbindung. Wenn Sie über mehrere Anwendungsserver verfügen, können Sie eine einzelne Instanz von msdtc auf einem Server ausführen (z. B. in der Datenbank oder auf einem der Anwendungsserver) und diese remote von allen Anwendungsservern verwenden, anstatt sie einzeln ausführen zu müssen ihre eigenen, aber ich weiß nicht, welche zusätzlichen Vorteile das hat.

+1

Ist es wirklich in SQL Server 2008 behoben? Ich verwende SQLS2008, und wenn ich eine zweite Verbindung mit derselben Verbindungszeichenfolge öffne, erhält die Transaktion eine verteilte GUID. Also ... ist das nur auf der Client-Seite oder wird es wirklich eine verteilte Transaktion? – Triynko

+0

Siehe http://msdn.microsoft.com/en-us/library/ms172070%28VS.90%29.aspx Ich habe es nicht für mich selbst getestet, aber nach den Dokumenten sollte es zumindest ein plausibles Szenario sein wo SQL 2008 verhält sich so. Vielleicht könnte es hilfreich sein, die Verbindungszeichenfolge zu optimieren, um das Pooling explizit zu steuern. – stombeur

+1

Sieht aus wie nicht mit SQL Server 2008 gelöst, Transaktion auf DTC mit derselben Verbindungszeichenfolge und lokaler Datenbank erhöht – mamu

-2

Wenn Sie SQL Server verwenden und @@ trancount überprüfen, ist der Wert 0, auch wenn Sie ein aktives TransactionScope haben.

+1

Es wird nicht Null sein; Ich habe es gerade getestet. Sie öffnen wahrscheinlich Ihre Verbindung vor dem Transaktionsbereich, was bedeutet, dass Ihre Verbindung überhaupt nicht an der Transaktion teilnimmt (etwas, das ich gerade gelernt habe, finden Sie in meinem Beitrag hier: http://stackoverflow.com/questions/2884863/under-what -circumstances-is-a-sqlconnection-automatisch-eingetragen-in-einem-Umgebung/2886326 # 2886326). Öffnen Sie entweder die Verbindung innerhalb des Transaktionsbereichs oder binden Sie Ihre vorhandene Transaktion explizit in den Bereich ein, indem Sie connection.EnlistTransaction (Transaction.Current) aufrufen. Führen Sie "select @@ trancount" aus, um dessen Nicht-Null zu sehen. – Triynko

1

Beachten Sie auch, dass wenn Sie eines Ihrer Objekte während der Transaktion ändern, werden sie nicht zurückgesetzt, es sei denn, Sie Code hinzufügen, um dies zu behandeln.

Siehe TransactionScope and rolling back object state

+0

Was? Wenn Sie über Datenbankobjekte sprechen, ist das nicht wahr. Wenn Sie Befehle für eine Verbindung erteilen, die im Transaktionsbereich angegeben ist, und Sie sie nicht festschreiben, werden die Änderungen nach dem Verwerfen des Bereichs zurückgerollt ... wie bei jeder anderen Transaktion auch. Wenn Sie nicht über Datenbankobjekte wie Dateien und Anwendungsvariablen sprechen, dann ja ... weil sie nichts mit der Transaktion zu tun haben. – Triynko

+0

Ich hatte sehr seltsames Verhalten bei der Verwendung von 'TransactionScope' und DDL - ich musste das 'TransactionScope' loswerden und normale, explizite Transaktionen verwenden, um es zu beheben. – Lucero

0

Hoffentlich jemand eines Tages helfen wird:

Wenn Sie eine Transaction mit mehreren SQL-Operationen innerhalb haben, wird der DTC nicht

  1. Sie identisch beteiligt bereitgestellt werden verwenden Verbindungszeichenfolge für jede Verbindung
  2. Verbindungen sind nicht verschachtelt.

I.e. offen, mach etwas, nah. offen, mach etwas, nah.

Jetzt für den Gotcha: wenn Sie jemals tun dies in Ihrem Prozess (auf einem anderen Thread)

SqlConnection.ClearAllPools()

und das geschieht zwischen zwei Operationen kommen - die DTC sofort beteiligt sein wird. Wenn das DTC nicht ausgeführt wird, wird eine Ausnahme ausgelöst.