sql >> Base de Datos >  >> RDS >> Sqlserver

Uso de TransactionScope con lectura no confirmada:¿es necesario con (nolock) en SQL?

Respuesta corta:No

Respuesta larga:

La simple definición de TransactionScope no define que se invocará ninguna lectura o escritura dentro de una transacción.

¡Para ejecutar algo dentro de una transacción, todavía tiene que abrir y confirmar una transacción!

Las TransactionOptions de TransactionScope para Timeout y IsolationLevel simplemente defina los predeterminados para cualquier transacción creada dentro del alcance sin esas opciones establecidas explícitamente. En realidad, TransactionScope crea una transacción, pero no estará activa sin abrir una nueva transacción. Internamente, esto hará algunas cosas complejas, clonando la transacción, etc... así que ignoremos esto...

Sin una transacción, no puede definir el nivel de aislamiento, cualquier declaración de selección se ejecutará con IsolationLevel.ReadCommitted porque este es el valor predeterminado de SQL Server.

También puede consultar session.Transaction.IsActive para ver si una transacción está actualmente activa para la sesión!

Echemos un vistazo al siguiente código, puse algunos comentarios para que quede un poco más claro

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

También puede ver cómo reacciona SQL Server a esas configuraciones usando SQL Server Profiler.

Simplemente cree un nuevo Trace y tenga cuidado con el Audit Login evento, el texto del evento incluirá el nivel de aislamiento y puede ver que en realidad hace un Audit Login cada vez que se crea una transacción, por ejemplo

 set transaction isolation level read uncommitted

--

Por favor, corríjame si alguna parte de esta información puede ser incorrecta, solo lo descubrí por mi cuenta, por lo que podría haber algún error potencial;)