Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Verwendung von TransactionScope mit read uncommitted - ist mit (nolock) in SQL notwendig?

Kurze Antwort:Nein

Lange Antwort:

Das bloße Definieren des TransactionScope definiert nicht, dass Lese- oder Schreibvorgänge innerhalb einer Transaktion aufgerufen werden.

Um etwas innerhalb einer Transaktion auszuführen, müssen Sie trotzdem eine Transaktion öffnen und festschreiben!

Die TransactionOptions des TransactionScope für Timeout und IsolationLevel Definieren Sie einfach die Standardwerte für alle Transaktionen, die innerhalb des Bereichs erstellt wurden, ohne dass diese Optionen explizit festgelegt wurden. Tatsächlich erstellt der TransactionScope eine Transaktion, aber er ist nicht aktiv, ohne eine neue Transaktion zu öffnen. Intern wird dies einige komplexe Dinge tun, die Transaktion klonen usw.... also ignorieren wir das...

Ohne eine Transaktion können Sie die Isolationsstufe nicht definieren, jede Select-Anweisung wird mit IsolationLevel.ReadCommitted ausgeführt da dies die Standardeinstellung von SQL Server ist.

Sie können auch session.Transaction.IsActive abfragen um zu sehen, ob gerade eine Transaktion für die Sitzung aktiv ist!

Lassen Sie uns einen Blick auf den folgenden Code werfen, ich habe einige Kommentare eingefügt, um es ein wenig klarer zu machen

using (var scope = new TransactionScope(TransactionScopeOption.Required,
                    new TransactionOptions()
                    {
                        IsolationLevel = IsolationLevel.ReadUncommitted
                    }))
{

    using (var session = sessionFactory.OpenSession())
    {
        // outside any transaction...
        var x = session.Transaction.IsActive; // false;

        // read will be done with SQL Server default (ReadCommited)
        var pp = session.Query<Page>().Where(p => p.Photos.Count() > 1).ToList();

        using (var transaction = session.BeginTransaction())
        {
            // will use ReadUncommitted according to the scope
            var y = session.Transaction.IsActive; // true;

            var p1 = session.Get<Page>(1);

            transaction.Commit();
        }
        using (var transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
        {
            // will use ReadCommitted according to the transaction initialization
            var y = session.Transaction.IsActive; // true;

            var p1 = session.Get<Page>(1);

            transaction.Commit();
        }

        scope.Complete();
    }
}

Sie können auch beobachten, wie SQL Server auf diese Einstellungen reagiert, indem Sie den SQL Server Profiler verwenden.

Erstellen Sie einfach einen neuen Trace und achten Sie auf den Audit Login -Ereignis enthält der Text des Ereignisses die Isolationsstufe und Sie können sehen, dass tatsächlich eine Audit Login durchgeführt wird jedes Mal, wenn eine Transaktion erstellt wird, zum Beispiel

 set transaction isolation level read uncommitted

--

Bitte korrigieren Sie mich, wenn eine dieser Informationen falsch sein könnte, ich habe das gerade selbst herausgefunden, daher könnte ein gewisses Fehlerpotenzial bestehen;)