Blocage sur la déclaration de suppression

11

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
K09
la source
5
Non, un blocage peut se produire dans d'autres scénarios en dehors de SELECT / UPDATE. Tout ce dont vous avez vraiment besoin, ce sont deux processus qui ont chacun besoin d'une ressource que l'autre détient. (1) Les instructions DELETE font-elles partie d'une transaction plus importante? (2) Pouvez-vous publier le XML de blocage quelque part, au lieu du texte de journal d'erreurs merdique?
Aaron Bertrand
Pourriez-vous s'il vous plaît publier le schéma de table d' dbo.UserDetailsDatainclure tous les index? De plus, savez-vous si ces instructions sont appelées avec les mêmes paramètres? Étant donné que les deux n'ont aucun journal utilisé, je me demande si tout ce que vous avez à faire est de sérialiser les appels, car ils se marchent les uns sur les autres.
Jon Seigel
Comment obtenir le XML? Vous avez l'erreur des journaux d'erreurs SQL Server. Les instructions sont appelées avec différents paramètres. Nous avons récemment ajouté un certain nombre d'index filtrés qui filtrent sur le champ UserDate.
K09
Attrapez l'événement de graphique de blocage dans le profileur. Ensuite, après l'avoir attrapé, faites un clic droit sur la ligne -> extraire les données d'événement -> enregistrez-le quelque part en tant que .xdl et publiez son contenu (c'est un xml) sur Pastebin (ou quelque part similaire).
Marian
1
Salut, XML publié ici ... j'espère que cela vous aidera! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

Réponses:

14

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 0acquiert un Uverrou de page update ( ) surPAGE: 12:1:5147422
  2. spid 166 ecid 3demande un Uverrouillage de page update ( ) sur la même page et est bloqué
  3. spid 54 ecid 2demande un Uverrouillage de page update ( ) 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 0et ecid 2sont des threads du même processus parent. Malheureusement, l'étape 2 se met en travers de cela et une impasse se produit.

Cela dit, vous ne devriez pas vraiment vous soucier de la raison pour laquelle 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 des lignes WHERE Username = @P1 AND UserDate = @P2, vous devez donc avoir un index sur ces colonnes.

Et bien sûr, vous avez un tel indice. La vraie question est de savoir 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 ne peut pas récupérer les colonnes supplémentaires dans l'opérateur de suppression d'index en 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 (aucun moyen pris en charge pour ce faire)
  4. Exécutez la requête sous isolement d'instantané (pas RCSI)

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

L'option 4 (merci Jack Douglas) a l'avantage de supprimer les blocages et ne devrait pas provoquer de "conflits de mise à jour", étant donné la nature disjointe des changements, mais elle nécessite l'activation de l'isolement de l'instantané au niveau de la base de données, 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 belle recherche d'index est ce que vous voulez vraiment.

Paul White 9
la source