J'ai un processus avec une sélection qui prend beaucoup de temps, de l'ordre de 5 à 10 minutes.
Je n’utilise pas NOLOCK pour le moteur de base de données MS SQL.
Parallèlement, un autre processus effectue des mises à jour et des insertions dans la même base de données et les mêmes tables.
Le premier processus a démarré et se termine récemment par un message.
SQLEXCEPTION: la transaction a été bloquée sur des ressources de verrouillage avec un autre processus et a été choisie comme victime du blocage.
Ce premier processus s'exécute sur d'autres sites dans des conditions identiques, mais avec des bases de données plus petites. Par conséquent, l'instruction select en question prend une période beaucoup plus courte (de l'ordre de 30 secondes environ). Sur ces autres sites, je ne reçois pas le message d'interblocage sur ces autres sites. Je n'ai pas non plus reçu ce message sur le site qui pose le problème au départ, mais je suppose que, à mesure que la base de données a grandi, je pense avoir franchi un certain seuil. Voici mes questions:
Q1: Le temps nécessaire à l'exécution d'une transaction peut-il rendre le processus associé plus susceptible d'être signalé comme victime d'un blocage?.
Non. Le SELECT est la victime car il n'a lu que les données. La transaction est donc associée à n coût inférieur . Elle est donc choisie comme victime:
Par défaut, le moteur de base de données choisit comme victime de l'impasse la session exécutant la transaction qui est la moins chère à restaurer . Sinon, un utilisateur peut spécifier la priorité des sessions dans une situation de blocage en utilisant l'instruction
SET DEADLOCK_PRIORITY
. DEADLOCK_PRIORITY peut être défini sur LOW, NORMAL ou HIGH, ou sur n'importe quel nombre entier compris entre -10 et 10.
Q2. Si j'exécute l'option select avec un indice NOLOCK, le problème sera-t-il résolu?
Non, pour plusieurs raisons:
Q3. Je soupçonne qu'un champ datetime vérifié dans le cadre de la clause WHERE de l'instruction select est à l'origine du temps de recherche lent. Puis-je créer un index basé sur ce champ? Est-ce conseillé?
Probablement. La cause de l'impasse est très probablement une base de données mal indexée.10 Les requêtes sont acceptables dans des conditions si étroites que je suis certain à 100% que votre cas est pas acceptable.
Avec une confiance de 99%, je déclare que votre impasse est gérée par une analyse de table volumineuse en conflit avec les mises à jour. Commencez par capturer le graphe de blocage pour analyser la cause. Vous devrez très probablement optimiser le schéma de votre base de données. Avant toute modification, lisez cette rubrique Conception d’index et les sous-articles.
Voici comment ce problème particulier de blocage s'est produit et comment il a été résolu. Il s'agit d'une base de données assez active avec 130 000 transactions effectuées quotidiennement. Les index dans les tables de cette base de données ont été initialement groupés. Le client nous a demandé de rendre les index non clusterisés. Dès que nous l'avons fait, l'impasse a commencé. Lorsque nous avons rétabli les index comme étant en cluster, le blocage s'est arrêté.
Les réponses ici valent la peine d'essayer, mais vous devriez également revoir votre code. Lisez en particulier la réponse de Polyfun ici: Comment se débarrasser de l’impasse dans une application SQL Server 2005 et C #?
Il explique le problème de simultanéité et explique comment l'utilisation de "with (updlock)" dans vos requêtes pourrait corriger votre situation de blocage - en fonction de ce que fait votre code. Si votre code suit ce modèle, il est probablement préférable de le corriger avant de recourir à des lectures de données modifiées, etc.