Causa de que un proceso sea víctima de un punto muerto

105

Tengo un proceso con un Select que tarda mucho en finalizar, del orden de 5 a 10 minutos.
Actualmente no estoy usando NOLOCK como una pista para el motor de base de datos MS SQL.
Al mismo tiempo, tenemos otro proceso que realiza actualizaciones e inserciones en la misma base de datos y las mismas tablas.
El primer proceso ha comenzado, recientemente para terminar prematuramente con un mensaje

SQLEXCEPTION: La transacción se bloqueó en los recursos de bloqueo con otro proceso y se eligió como la víctima del bloqueo.

Este primer proceso se ejecuta en otros sitios en condiciones idénticas pero con bases de datos más pequeñas y, por lo tanto, la declaración de selección en cuestión toma un período de tiempo mucho más corto (del orden de 30 segundos aproximadamente). En estos otros sitios, no recibo el mensaje de interbloqueo en estos otros sitios. Tampoco recibí este mensaje en el sitio que tenía el problema inicialmente, pero supongo que, a medida que la base de datos ha crecido, creo que debo haber cruzado algún umbral. Aquí están mis preguntas:

  1. ¿Podría el tiempo que tarda en ejecutarse una transacción hacer que el proceso asociado sea más probable que sea marcado como víctima de un punto muerto?
  2. Si ejecuto la selección con una pista NOLOCK, ¿esto eliminará el problema?
  3. Sospecho que un campo de fecha y hora que se verifica como parte de la cláusula WHERE en la declaración de selección está causando el tiempo de búsqueda lento. ¿Puedo crear un índice basado en este campo? Es aconsejable
Elliott
fuente
Respuesta parcial al punto 1: No confunda un punto muerto con un tiempo de espera. Si estaba sufriendo un tiempo de espera, el tiempo necesario para finalizar una transacción puede ser responsable de la terminación anormal de la otra. Además, sería útil saber en qué recurso está bloqueando (¿es un índice o una tabla?).
NealB
1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow

Respuestas:

128

P1: ¿Podría el tiempo que tarda en ejecutarse una transacción hacer que el proceso asociado sea más probable que se marque como una víctima de interbloqueo?

No. El SELECT es la víctima porque solo había leído datos, por lo tanto, la transacción tiene un costo menor asociado, por lo que se elige como la víctima:

De forma predeterminada, el motor de base de datos elige como víctima del interbloqueo la sesión que ejecuta la transacción que es menos costosa de revertir . Alternativamente, un usuario puede especificar la prioridad de las sesiones en una situación de interbloqueo usando la SET DEADLOCK_PRIORITYdeclaración. DEADLOCK_PRIORITY se puede establecer en LOW, NORMAL o HIGH, o alternativamente se puede establecer en cualquier valor entero en el rango (-10 a 10).

Q2. Si ejecuto la selección con una pista NOLOCK, ¿esto eliminará el problema?

No. Por varias razones:

Q3. Sospecho que un campo de fecha y hora que se verifica como parte de la cláusula WHERE en la declaración de selección está causando el tiempo de búsqueda lento. ¿Puedo crear un índice basado en este campo? Es aconsejable

Probablemente. Es muy probable que la causa del interbloqueo sea una base de datos mal indexada. Las consultas de 10 minutos son aceptables en condiciones tan estrechas, que estoy 100% seguro de que en su caso no es aceptable.

Con un 99% de confianza, declaro que su punto muerto está marcado por un escaneo de tabla grande que entra en conflicto con las actualizaciones. Empiece por capturar el gráfico de interbloqueo para analizar la causa. Es muy probable que tenga que optimizar el esquema de su base de datos. Antes de realizar cualquier modificación, lea este tema Diseño de índices y los subartículos.

Remus Rusanu
fuente
Gracias por su completa respuesta. Aunque supongo que todavía tengo una pregunta. ¿Por qué estaría obteniendo la situación de punto muerto solo en un entorno y no en otro? Aunque el software es el mismo. Su respuesta sugiere que la cantidad de tiempo para ejecutar la consulta Select no hace una diferencia y es el hecho de que es una consulta Select per se lo que está causando que el proceso falle. Pero entonces, ¿por qué solo cuando la consulta de selección tarda mucho en ejecutarse?
Elliott
4
La longitud de la consulta no influye en la elección de la víctima del interbloqueo . Hace una diferencia en causar el punto muerto por al menos dos factores: 1) probabilidades simples. Cuanto más larga sea la consulta, es más probable que se superpongan actualizaciones simultáneas y se produzcan puntos muertos. 2) una tabla más grande puede usar un plan de consulta completamente diferente, uno que sea susceptible a interbloqueos.
Remus Rusanu
12

Así es como ocurrió realmente este problema particular de interbloqueo y cómo se resolvió realmente. Esta es una base de datos bastante activa con 130.000 transacciones diarias. Los índices de las tablas de esta base de datos se agruparon originalmente. El cliente nos pidió que hiciéramos los índices no agrupados. Tan pronto como lo hicimos, comenzó el interbloqueo. Cuando restablecimos los índices como agrupados, el interbloqueo se detuvo.

Elliott
fuente
34
¿Alguien puede explicar por qué? (Las soluciones mágicas no son muy útiles)
OGrandeDiEnne
1
Este chico lo explica en su publicación: mssqltips.com/sqlservertip/2517/…
siga0984
6

Vale la pena probar las respuestas aquí, pero también debe revisar su código. Específicamente, lea la respuesta de Polyfun aquí: ¿Cómo deshacerse del interbloqueo en una aplicación SQL Server 2005 y C #?

Explica el problema de la concurrencia y cómo el uso de "with (updlock)" en sus consultas podría corregir su situación de interbloqueo, dependiendo realmente de lo que esté haciendo exactamente su código. Si su código sigue este patrón, es probable que esta sea una mejor solución antes de recurrir a lecturas sucias, etc.

Peter Barton
fuente