web-dev-qa-db-fra.com

Blocage sur la déclaration de suppression

Je reçois un blocage lors de l'exécution d'un travail SQL Server. Le blocage se produit sur une simple instruction DELETE. J'aurais pensé qu'il devrait y avoir une requête SELECT/UPDATE en cours d'exécution pour provoquer le blocage? Mais il semble que ce soit DELETE/DELETE deadlock ...

Ce que je recherche, c'est pourquoi j'obtiens un blocage DELETE/DELETE. Il s'agit (à ma connaissance) de différents paramètres.

Des idées? Merci.

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
11
K09

Ce que je recherche, c'est pourquoi j'obtiens un blocage DELETE/DELETE.

Il semble que l'impasse se produise parce que:

  1. spid 54 ecid 0 acquiert un verrouillage de page de mise à jour (U) sur PAGE: 12:1:5147422
  2. spid 166 ecid 3 demande un verrouillage de page de mise à jour (U) sur la même page et est bloqué
  3. spid 54 ecid 2 demande un verrouillage de mise à jour (U) sur la même page ...

Les pages sont en cours de prélecture pour la requête, avec des verrous de mise à jour acquis par ecid 0. C'est l'étape 1 ci-dessus. À l'étape 3, un thread enfant de la même requête parallèle (ecid 2) demande le même verrou. Normalement, ce ne serait pas un problème. SQL Server connaît ecid 0 et ecid 2 sont des fils du même processus parent. Malheureusement, l'étape 2 s'y oppose et une impasse se produit.

Cela dit, vous ne devriez pas vraiment vous soucier de pourquoi l'impasse se produit, la question importante est de savoir comment l'éviter. La réponse est de fournir un chemin d'accès efficace pour le DELETE. L'instruction doit trouver les lignes WHERE Username = @P1 AND UserDate = @P2, vous devriez donc avoir un index sur ces colonnes.

Et bien sûr, vous avez un tel indice. La vraie question explique pourquoi vos problèmes ont commencé à se produire après avoir ajouté des index filtrés.

La réponse à cette question est que des informations supplémentaires sur les colonnes sont nécessaires pour localiser les lignes d'index filtrées à supprimer (et pour vérifier leurs prédicats). Si la requête utilise un plan d'exécution étroit/par ligne , le moteur d'exécution n'est pas en mesure de récupérer les colonnes supplémentaires dans l'opérateur de suppression d'index cluster, comme il le ferait dans un plan large/par index.

Vous pouvez trouver plus de détails à ce sujet et un exemple concret dans cet article de blog .

Dans ce cas, les informations de colonne doivent provenir de la partie du plan à droite de la suppression d'index en cluster, et donc une analyse d'index en cluster parallèle est utilisée, et vous obtenez une requête lente avec un potentiel de blocage élevé.

La réponse consiste à effectuer l'une des opérations suivantes:

  1. Supprimer les index filtrés
  2. Ajouter des colonnes d'index/d'inclusion/de prédicat filtrées à l'index de nom/date existant
  3. Forcer un plan de mise à jour étendu (pas de méthode prise en charge pour ce faire)
  4. Exécutez la requête sous l'isolement de l'instantané (pas RCSI)

L'option 2 serait ma préférence.

L'option 4 (merci Jack Douglas) a l'avantage de supprimer les interblocages, et ne devrait pas provoquer des "conflits de mise à jour", étant donné la nature disjointe des changements, mais elle nécessite d'activer l'isolement de l'instantané au niveau de la base de données, en modifiant explicitement le niveau d'isolement, et ne résoudra pas le problème sous-jacent: vous vous retrouverez toujours avec une analyse de table parallèle inutile, où une recherche d'index Nice est ce que vous voulez vraiment.

14
Paul White 9