Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Uso de TransactionScope com leitura não confirmada - é necessário com (nolock) no SQL?


Resposta curta:Não

Resposta longa:


Apenas definir o TransactionScope não define que qualquer leitura ou escrita será invocada dentro de uma transação.

Para executar algo dentro de uma transação, você ainda precisa abrir e confirmar uma transação!

As TransactionOptions do TransactionScope para Timeout e IsolationLevel apenas defina os padrões para qualquer transação criada dentro do escopo sem essas opções explicitamente definidas. Na verdade, o TransactionScope cria uma transação, mas não estará ativo sem abrir uma nova transação. Internamente, isso fará algumas coisas complexas, clonando a transação etc ... então vamos ignorar isso ...

Sem uma transação, você não pode definir o nível de isolamento, qualquer instrução select será executada com IsolationLevel.ReadCommitted porque este é o padrão do SQL Server.

Você também pode consultar session.Transaction.IsActive para ver se uma transação está atualmente ativa para a sessão!

Vamos dar uma olhada no código a seguir, eu coloquei alguns comentários para deixar um pouco mais 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();
    }
}

Você também pode observar como o SQL Server reage a essas configurações usando o SQL Server Profiler.

Basta criar um novo Trace e ficar atento ao Audit Login evento, o texto do evento incluirá o nível de isolamento e você poderá ver que ele realmente faz um Audit Login cada vez que uma transação é criada, por exemplo
 set transaction isolation level read uncommitted

--

Por favor, corrija-me se alguma dessas informações estiver errada, acabei de descobrir isso sozinho, então pode haver algum potencial de falha;