sql >> Base de Datos >  >> RDS >> Sqlserver

¿Por qué esta consulta de SQL Server se bloquea?

  • el proceso 9196a8 tiene la página 151867, ranura 174 en modo X y quiere la página 140302, ranura 31 en modo S
  • el proceso 88b5b8 tiene la página 140302, ranura 31 en modo X y quiere la página 151867, ranura 174 en modo S
  • las dos eliminaciones se ejecutan bajo isolationlevel="repeatable read (3)"

Entonces, el interbloqueo ocurre en el montón base de la tabla (los bloqueos RID en lugar de los bloqueos de teclas implican un montón, no un Btree). El alto nivel de aislamiento (probablemente causado por DTC, a juzgar por el nombre exacto) hace que la configuración de RCSI sea irrelevante.

¿De qué tipo son las columnas PARTYEXTERNALREF y PARTYTYPE? Los parámetros pasados ​​son NVARCHAR (es decir, Unicode) y si las columnas son VARCHAR (es decir, Ascii), entonces debido a las reglas de precedencia del tipo de datos no se utilizaría el índice NC. Debido al escaneo de la tabla involucrado, junto con el alto nivel de aislamiento en uso, un interbloqueo es casi inevitable.

La solución sería usar parámetros de tipo VARCHAR para @P0 y @P1 para que el índice NC se aproveche para evitar el escaneo de la tabla.

Si los parámetros ya son del tipo VARCHAR y puede confirmar desde el plan de ejecución que se usa una búsqueda en el NC, mi primera pregunta sería qué más está haciendo la transacción, además de las declaraciones de eliminación?

Por cierto, solo das el nombre del índice NC, pero supongo que está en (PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID) .

Actualizar

Ya que tu comentario dice que las columnas son NVARCHAR entonces la hipótesis de escaneo de tablas probablemente sea incorrecta. Hay tres posibilidades más para causar un interbloqueo que necesitan investigación:

  • cualquier otra declaración ejecutada por la transacción antes de DELETE (esta es la más probable)
  • cualquier superposición en las filas seleccionadas por dos sentencias DELETE involucradas en el interbloqueo
  • colisión de hash

Para las dos primeras hipótesis solo tú puedes hacer algo ahora mismo (investiga si son correctas). Para el último te puedo decir cómo verificarlo, pero no es baladí. Es poco probable que suceda y un poco difícil de probar, pero es posible. Como conoce el caso de interbloqueo (el XML adjunto), utilícelo como base de investigación:

  • restaurar una copia puntual de la base de datos con parada en 2011-09-02T19:00:29.690
  • ejecutar DBCC TRACEON(3604,-1)
  • utilizando DBCC PAGE (<restored db id>, 1, 151867, 3) inspeccionar los valores en la ranura 174
  • usando DBCC PAGE(, 1, 140302, 3)` inspeccione los valores en la ranura 31
  • ejecutar SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF = ... AND ISCOUNTERPARTY='N' and PARTYID=... y pasar los valores leídos arriba
  • compara los valores de hash de bloqueo resultantes, si coinciden, entonces tiene una colisión de hash y esto causó el interbloqueo.