Cómo rastrear el bloqueo que ocurre por menos de un segundo - SQL Server

14

Estoy tratando de solucionar un problema de bloqueo que ocurre por menos de un segundo. La aplicación OLTP es muy sensible y debe tener un tiempo de respuesta de menos de 200 ms para algunas transacciones según el acuerdo de nivel de servicio acordado. Tuvimos algunos problemas de escalada de bloqueo con la nueva versión del código que pudimos resolver reduciendo el tamaño del lote en las actualizaciones. Incluso con el pequeño tamaño de lote, sospechamos que el nuevo sp está bloqueando las mismas filas que las transacciones OLTP están actualizando.

Necesito encontrar la sesión que se está bloqueando y el recurso está esperando. Según mi entendimiento, el "umbral de proceso bloqueado" puede establecerse por un mínimo de 1 segundo, por lo que esto no capturará el bloqueo.

Estoy experimentando con wait_info y wait_completed x eventos.

¿Hay alguna otra forma de rastrear esto? Gracias

jesijesi
fuente
misma pregunta así por el mismo usuario: stackoverflow.com/questions/38407021/…
TheGameiswar

Respuestas:

10

Como está específicamente interesado en bloquear en lugar de esperar en general, el locks_lock_waitsevento extendido suena más adecuado.

Con un filtro encendido increment >= 200

CREATE EVENT SESSION [locks_lock_waits] ON SERVER 
ADD EVENT sqlserver.locks_lock_waits(
        ACTION(sqlserver.sql_text)
            WHERE  ( [sqlserver].[is_system] = 0
                     AND [increment] >= 200
                     AND [counter] <= 1000 ) 
    )
ADD TARGET package0.ring_buffer;

GO

ALTER EVENT SESSION [locks_lock_waits]  
ON SERVER  STATE = start;  

Lo anterior reúne las declaraciones que esperan en los bloqueos durante el umbral de tiempo, pero no proporciona el recurso de bloqueo específico.

Nunca he usado este evento y no tengo idea de cuánto sobrecargaría esta sesión en su servidor de producción.

Encontré este video sobre el tema. Eso recomienda encarecidamente filtrar counterpara reducir la cantidad de eventos recopilados y lo he hecho anteriormente.

También menciona un antiguo comando indocumentado heredado

dbcc lock(StallReportThreshold, 200) -- 200 is threshold in ms

Que (si el indicador de seguimiento 3605 está habilitado) volca información limitada, como la siguiente, en el registro de errores de SQL Server.

El proceso 53 esperó 6844 ms para el bloqueo S en RID: 2: 1: 120: 2 resultado: OKWAIT

Solo menciono esto de pasada, ya que los eventos extendidos serían claramente preferibles de todos modos, ya que está documentado y es mucho más poderoso.

Martin Smith
fuente
Probé locks_lock_waits y, como dijiste, no tiene la información del recurso. Pero no sabía que el incremento era tiempo. Buena información dbcc lock, se ve muy bien. ¿Sabe cuánto tiempo está disponible esa información antes de que pueda ser volcada al registro de errores?
jesijesi
Lo siento, no me puse en claro. Estaba preguntando, ¿cuánto tiempo tenemos hasta que ejecutemos el comando dbcc lock. Por ejemplo, el bloqueo ocurre y si ejecuto dbcc lock después de una hora, ¿aún recibo la información?
jesijesi
@jesijesi: nunca antes había oído hablar de eso. No tengo más información al respecto. Ni siquiera sé los parámetros para pasar para desactivarlo. Pero usted ejecuta dbcc lock(StallReportThreshold, 200) primero y genera la información una vez que se supera el umbral, siempre que el indicador de seguimiento 3605 esté habilitado. SQL Server no recopila esta información en caso de que pueda ejecutarla más tarde.
Martin Smith
2
Gracias. simplemente agregando un enlace que tiene una función útil para convertir los valores resource_0,1,2 en xevents. sqlnotes.info/2011/10/24/…
jesijesi
5

Si está interesado en bloquear, hay varios eventos extendidos disponibles:

lock_acquired
lock_released
lock_escalation

Los primeros dos eventos tienen una durationcolumna en (microsegundos) que puede filtrar para sus umbrales. También tienen una resource_descriptionacción que le dará algunos detalles sobre los recursos involucrados.

El lock_escalationevento también tiene una statementacción que puede agregar para recopilar la instrucción T-SQL que desencadenó la escalada de bloqueo. También tiene escalation_cause. Aquí hay una sesión de muestra:

CREATE EVENT SESSION [locking] ON SERVER 
ADD EVENT sqlserver.lock_acquired( SET collect_resource_description = (1) ),
ADD EVENT sqlserver.lock_escalation( SET collect_statement = (1) ),
ADD EVENT sqlserver.lock_released( SET collect_resource_description = (1) )
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO

Sospecho que probablemente haya una razón por la que no puede establecer el umbral del informe de proceso bloqueado en menos de un segundo: el bloqueo es perfectamente normal en un RDBMS: el motor de la base de datos debe bloquear los recursos para protegerlos. Aunque no existe una definición oficial de cuándo el bloqueo se convierte en bloqueo, el bloqueo del tic-tac en menos de un segundo me parece algo normal.

wBob
fuente
1
el bloqueo se convierte en bloqueo tan pronto como a otra persona se le niega el acceso al recurso y tiene que esperar debido al bloqueo.
Martin Smith
Gracias, estoy planeando usar lock_acquired con el campo de duración.
jesijesi
Buena suerte. Como se encuentra en SQL Server 2014, puede usar tablas OLTP en memoria con procesos almacenados compilados de forma nativa que ofrecen una opción de alto rendimiento sin bloqueo. También podría mirar el aislamiento de instantáneas.
wBob