Warum ist System.Transactions TransactionScope standardmäßig auf Isolationsebene serialisierbar?

75

Ich frage mich nur, was ein guter Grund für die Verwendung von Serializable als Standard-Isolationsstufe beim Erstellen eines System.Transactions TransactionScope sein kann , da mir keine einfällt (und es scheint, dass Sie die Standardeinstellung über nicht ändern können, web/app.configsodass Sie sie immer festlegen müssen dein Code)

using(var transaction = TransactionScope()) 
{
    ... //creates a Transaction with Serializable Level
}

Stattdessen muss ich immer Boilerplate-Code wie folgt schreiben:

var txOptions = new System.Transactions.TransactionOptions();
txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

using(var transaction = new TransactionScope(TransactionScopeOption.Required, txOptions)) 
{
    ...
}

Irgendwelche Ideen?

Bernhard Kircher
quelle
1
Verschieben Sie diesen Code in eine Hilfsmethode, und dieses Problem wird Sie nie wieder stören.
usr

Antworten:

91

Tatsache Serializableist, dass die Standardeinstellung aus Zeiten stammt, in denen .NET noch nicht einmal (vor dem Jahr 1999) aus der DTC- Programmierung ( Distributed Transaction Coordinator ) veröffentlicht wurde.

DTC verwendet eine native ISOLATIONLEVEL- Aufzählung:

ISOLATIONLEVEL_SERIALIZABLE Von einer aktuellen Transaktion gelesene Daten können erst nach Abschluss der aktuellen Transaktion von einer anderen Transaktion geändert werden. Es können keine neuen Daten eingefügt werden, die sich auf die aktuelle Transaktion auswirken würden. Dies ist die sicherste Isolationsstufe und die Standardeinstellung, ermöglicht jedoch die niedrigste Parallelitätsstufe.

.NET TransactionScopebasiert auf diesen Technologien.

Die nächste Frage lautet nun: Warum wird DTC ISOLATIONLEVEL_SERIALIZABLEals Standardtransaktionsstufe definiert ? Ich nehme an, das liegt daran, dass DTC um das Jahr 1995 herum entworfen wurde (sicher vor 1999). Zu dieser Zeit war der SQL-Standard SQL-92 (oder SQL2).

Und hier ist, was SQL-92 über Transaktionsebenen sagt:

Eine SQL-Transaktion hat eine Isolationsstufe, die READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ oder SERIALIZABLE lautet. Die Isolationsstufe einer SQL-Transaktion definiert den Grad, in dem die Operationen auf SQL-Daten oder Schemas in dieser SQL-Transaktion von den Auswirkungen von Operationen auf SQL-Daten oder Schemas in gleichzeitigen SQL-Transaktionen beeinflusst werden und diese beeinflussen können. Die Isolationsstufe einer SQL-Transaktion ist standardmäßig SERIALIZABLE . Die Ebene kann explizit von der festgelegt werden <set transaction statement>.

Die Ausführung von gleichzeitigen SQL-Transaktionen auf Isolationsebene SERIALIZABLE ist garantiert serialisierbar. Eine serialisierbare Ausführung ist definiert als eine Ausführung der Operationen der gleichzeitigen Ausführung von SQL-Transaktionen, die den gleichen Effekt wie eine serielle Ausführung derselben SQL-Transaktionen erzeugt. Eine serielle Ausführung ist eine Ausführung, bei der jede SQL-Transaktion vollständig ausgeführt wird, bevor die nächste SQL-Transaktion beginnt.

Simon Mourier
quelle
50

Ein nützlicher Weg, um das Schreiben von Boilerplate-Code zu reduzieren, besteht darin, ihn in eine Builder-Klasse wie folgt zu verpacken:

public static class TransactionScopeBuilder
{
    /// <summary>
    /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server
    /// </summary>
    /// <returns>A transaction scope</returns>
    public static TransactionScope CreateReadCommitted()
    {
        var options = new TransactionOptions
        {
            IsolationLevel = IsolationLevel.ReadCommitted,
            Timeout = TransactionManager.DefaultTimeout
        };

        return new TransactionScope(TransactionScopeOption.Required, options);
    } 
}

Dann können Sie es beim Erstellen eines Transaktionsbereichs folgendermaßen verwenden:

using (var scope = TransactionScopeBuilder.CreateReadCommitted())
{
    //do work here
}

Sie können der Builder-Klasse nach Bedarf weitere allgemeine Standardeinstellungen für den Transaktionsbereich hinzufügen.

Mandel
quelle
1
Dies ist eigentlich das gleiche, was ich getan habe, um einen zentralen Ort zu haben, an dem ich das "Standard" -Transaktionsfernrohr für meine Anwendungsfälle erhalten kann
Bernhard Kircher
29

Nun, ich denke, dies ist eine dieser Fragen, die "nur der Designer definitiv kennen würde". Aber hier sind trotzdem meine zwei Cent:

Serializable ist zwar die "einschränkendste" Isolationsstufe (in Bezug auf das Sperren, in einem sperrbasierten RDBMS und damit gleichzeitigen Zugriff, Deadlocks usw.), aber auch die "sicherste" Isolationsstufe (in Bezug auf die Datenkonsistenz).

Während in Szenarien wie Ihren zusätzliche Arbeit erforderlich ist (wurde dies bereits getan ;-), ist es sinnvoll, standardmäßig die sicherste Variante zu wählen. SQL Server (T / SQL) verwendet READ COMMITTED aus anderen Gründen :-)

Es wäre dann eine schlechte Idee, es durch Konfiguration veränderbar zu machen, da Sie durch Fummeln an der Konfiguration eine perfekt funktionierende Anwendung in eine defekte umwandeln könnten (weil sie möglicherweise einfach nicht für die Verwendung mit irgendetwas anderem ausgelegt ist). Um das Argument umzukehren, können Sie durch "Hardcodierung" der Isolationsstufe sicherstellen, dass Ihre Anwendung wie erwartet funktioniert. Die Isolationsstufe passt wahrscheinlich nicht zu einer Konfigurationsoption (während das Transaktionszeitlimit tatsächlich ist).

Christian.K
quelle
3
"Sie könnten eine perfekt funktionierende Anwendung auf eine kaputte rendern" +1
Steven
2
Beachten Sie, dass selbst eine Isolationsstufe von serialisierbar noch keine Garantie dafür ist, dass keine Währungsprobleme auftreten können.
Steven
@ Christian.K Danke für deine Antwort. Sie haben Recht - nur der Designer weiß es. Vielleicht habe ich nur ein Problem mit der Serialisierbarkeit, weil ich eher an Datenbanken denke, wenn ich die Isolationsstufe höre. Serialisierbar kann ein guter Standard für andere Transaktionsanbieter sein.
Bernhard Kircher