Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

L'uso di TransactionScope con read uncommitted - è necessario con (nolock) in SQL?

Risposta breve:No

Risposta lunga:

La semplice definizione di TransactionScope non definisce che qualsiasi lettura o scrittura verrà invocata all'interno di una transazione.

Per eseguire qualcosa all'interno di una transazione, devi comunque aprire e confermare una transazione!

Le TransactionOptions del TransactionScope per Timeout e IsolationLevel basta definire i predefiniti per qualsiasi transazione creata all'interno dell'ambito senza tali opzioni impostate in modo esplicito. In realtà TransactionScope crea una Transazione ma non sarà attiva senza aprire una nuova Transazione. Internamente questo farà alcune cose complesse, clonando la transazione ecc... quindi ignoriamo questo...

Senza una transazione non è possibile definire il livello di isolamento, qualsiasi istruzione select verrà eseguita con IsolationLevel.ReadCommitted perché questa è l'impostazione predefinita di SQL Server.

Puoi anche interrogare session.Transaction.IsActive per vedere se una transazione è attualmente attiva per la sessione!

Diamo un'occhiata al codice seguente, ho inserito alcuni commenti per renderlo un po' più chiaro

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();
    }
}

Puoi anche osservare come SQL Server reagisce a tali impostazioni utilizzando SQL Server Profiler.

Basta creare una nuova traccia e fare attenzione al Audit Login evento, il testo dell'evento includerà il livello di isolamento e puoi vedere che esegue effettivamente un Audit Login ogni volta che viene creata una transazione, ad esempio

 set transaction isolation level read uncommitted

--

Per favore correggimi se una qualsiasi di queste informazioni potrebbe essere sbagliata, l'ho appena capito da solo, quindi potrebbe esserci un potenziale di errore;)