Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Utilisation de TransactionScope avec lecture non validée - est-ce nécessaire avec (nolock) dans SQL ?

Réponse courte :Non

Réponse longue :

Le simple fait de définir TransactionScope ne définit pas que toute lecture ou écriture sera invoquée dans une transaction.

Pour exécuter quelque chose dans une transaction, vous devez toujours ouvrir et valider une transaction !

Les TransactionOptions du TransactionScope pour Timeout et IsolationLevel définissez simplement les valeurs par défaut pour toute transaction créée dans la portée sans que ces options ne soient explicitement définies. En fait, TransactionScope crée une transaction mais elle ne sera pas active sans ouvrir une nouvelle transaction. En interne, cela fera des choses complexes, clonant la transaction, etc... alors ignorons cela...

Sans transaction, vous ne pouvez pas définir le niveau d'isolement, toute instruction select sera exécutée avec IsolationLevel.ReadCommitted car c'est la valeur par défaut de SQL Server.

Vous pouvez également interroger session.Transaction.IsActive pour voir si une transaction est actuellement active pour la session !

Jetons un œil au code suivant, j'ai mis quelques commentaires pour le rendre un peu plus clair

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

Vous pouvez également voir comment SQL Server réagit à ces paramètres à l'aide du SQL Server Profiler.

Créez simplement une nouvelle trace et faites attention à la Audit Login événement, le texte de l'événement inclura le niveau d'isolement et vous pouvez voir qu'il fait en fait un Audit Login chaque fois qu'une transaction est créée, par exemple

 set transaction isolation level read uncommitted

--

Veuillez me corriger si l'une de ces informations peut être erronée, je viens de comprendre cela par moi-même, il pourrait donc y avoir un potentiel d'échec ;)