Punto muerto en la declaración de eliminación

11

Tengo un punto muerto cuando se ejecuta un trabajo de SQL Server. El punto muerto se produce en una simple declaración DELETE. ¿Pensé que tendría que haber una consulta SELECT / UPDATE ejecutándose para causar el punto muerto? Pero parece que es DELETE / DELETE deadlock ...

Lo que estoy buscando es por qué obtengo un punto muerto DELETE / DELETE. Es (que yo sepa) pasar diferentes parámetros.

¿Algunas ideas? Gracias.

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
fuente
55
No, puede producirse un punto muerto en otros escenarios fuera de SELECCIONAR / ACTUALIZAR. Todo lo que realmente necesita son dos procesos, cada uno de los cuales necesita un recurso que el otro tenga. (1) ¿Son las declaraciones DELETE parte de una transacción más grande? (2) ¿Puede publicar el XML de punto muerto en algún lugar, en lugar del texto de registro de error de mierda?
Aaron Bertrand
¿Podría publicar el esquema de tabla para dbo.UserDetailsDataincluir todos los índices? Además, ¿sabe si esas declaraciones se invocan con los mismos parámetros? Dado que ambos tienen un registro cero, me pregunto si todo lo que necesita hacer es serializar las llamadas porque se pisan entre sí.
Jon Seigel
¿Cómo obtengo el XML? Obtuve el error de los registros de errores de SQL Server. Las declaraciones se llaman con diferentes parámetros. Recientemente agregamos una cantidad de índices filtrados que se filtran en el campo UserDate.
K09
Captura el evento de gráfico de punto muerto en Profiler. Luego, después de atraparlo, haga clic derecho en la fila -> extraer datos del evento -> guárdelo como un archivo .xdl en algún lugar y publique su contenido (es un xml) en Pastebin (o en algún lugar similar).
Marian
1
Hola, XML publicado aquí ... ¡espero que esto ayude! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

Respuestas:

14

Lo que estoy buscando es por qué obtengo un punto muerto DELETE / DELETE.

Parece que el punto muerto ocurre porque:

  1. spid 54 ecid 0adquiere un Ubloqueo de página de actualización ( ) enPAGE: 12:1:5147422
  2. spid 166 ecid 3solicita un Ubloqueo de página de actualización ( ) en la misma página y está bloqueado
  3. spid 54 ecid 2solicita un Ubloqueo de página de actualización ( ) en la misma página ...

Las páginas se están recuperando previamente para la consulta, con bloqueos de actualización adquiridos por ecid 0. Ese es el paso 1 anterior. En el paso 3, un subproceso secundario de la misma consulta paralela ( ecid 2) solicita el mismo bloqueo. Normalmente esto no sería un problema. SQL Server sabe ecid 0y ecid 2son hilos del mismo proceso padre. Desafortunadamente, el paso 2 se interpone en el camino de esto, y se produce un punto muerto.

Dicho esto, no debería preocuparte mucho por qué se produce el punto muerto, la pregunta importante es cómo evitarlo. La respuesta es proporcionar una ruta de acceso eficiente para DELETE. La instrucción necesita encontrar filas WHERE Username = @P1 AND UserDate = @P2, por lo que debe tener un índice en estas columnas.

Y, por supuesto, tienes ese índice. La verdadera pregunta es por qué sus problemas comenzaron a ocurrir después de agregar índices filtrados.

La respuesta a eso es que se necesita información de columna adicional para ubicar las filas de índice filtradas para eliminar (y verificar sus predicados). Si la consulta utiliza un plan de ejecución estrecho / por fila , el motor de ejecución no puede recuperar las columnas adicionales en el operador Eliminar índice agrupado, como lo haría en un plan amplio / por índice.

Puede encontrar más detalles al respecto y un ejemplo trabajado en esta publicación de blog .

En este caso, la información de la columna debe provenir de la parte del plan a la derecha de la Eliminación de índice agrupado, por lo que se utiliza un escaneo de índice agrupado paralelo, y obtiene una consulta lenta con un alto potencial de punto muerto.

La respuesta es hacer uno de los siguientes:

  1. Eliminar los índices filtrados
  2. Agregue columnas de clave de índice / incluir / predicado filtradas al índice de nombre / fecha existente
  3. Forzar un plan de actualización amplio (no hay forma compatible de hacerlo)
  4. Ejecute la consulta bajo aislamiento de instantánea (no RCSI)

La opción 2 sería mi fuerte preferencia.

La opción 4 (gracias Jack Douglas) tiene la ventaja de eliminar puntos muertos, y no debería causar ningún "conflicto de actualización", dada la naturaleza disjunta de los cambios, pero requiere habilitar el aislamiento de instantáneas en el nivel de la base de datos, cambiando explícitamente el nivel de aislamiento, y no solucionará el problema subyacente : aún terminará con un escaneo de tabla paralela derrochador, donde una buena búsqueda de índice es lo que realmente desea.

Paul White 9
fuente