Como controlar o bloqueio que ocorre por menos de um segundo - SQL Server

14

Estou tentando solucionar um problema de bloqueio que ocorre por menos de um segundo. O aplicativo OLTP é muito sensível e precisa ter um tempo de resposta inferior a 200ms para algumas transações, conforme o SLA acordado. Tivemos alguns problemas de escalação de bloqueios com o novo lançamento de código que pudemos resolver com a redução do tamanho do lote nas atualizações. Mesmo com o tamanho pequeno do lote, suspeitamos que o novo sp esteja bloqueando as mesmas linhas que as transações OLTP estão atualizando.

Preciso encontrar a sessão que está sendo bloqueada e o recurso está aguardando. De acordo com meu entendimento, "limite do processo bloqueado" pode ser definido por no mínimo 1 segundo e, portanto, isso não capturará o bloqueio.

Estou experimentando os eventos wait_info e wait_completed x.

Existe alguma outra maneira de rastrear isso. obrigado

jesijesi
fonte
mesma pergunta sobre o mesmo usuário: stackoverflow.com/questions/38407021/… #
TheGameiswar

Respostas:

10

Como você está especificamente interessado em bloquear, em vez de esperar em geral, o locks_lock_waitsevento estendido parece mais adequado.

Com um filtro ligado 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;  

O item acima reúne as instruções aguardando bloqueios pelo tempo limite, mas não fornece o recurso de bloqueio específico.

Eu nunca usei esse evento e não tenho ideia de quanto sobrecarga essa sessão causaria no seu servidor de produção.

Encontrei este vídeo sobre o assunto. Isso recomenda enfaticamente a filtragem counterpara reduzir o número de eventos coletados, e eu fiz isso acima.

Também menciona um antigo comando não documentado legado

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

Qual (se o sinalizador de rastreamento 3605 estiver ativado) despeja informações limitadas, como as abaixo, no log de erros do SQL Server.

O processo 53 esperou 6844 ms pelo bloqueio S no RID: 2: 1: 120: 2 resultado: OKWAIT

Eu apenas mencionei isso de passagem, pois os eventos estendidos seriam claramente preferíveis de qualquer maneira, pois estão documentados e muito mais poderosos.

Martin Smith
fonte
Testei locks_lock_waits e, como você disse, não possui as informações do recurso. Mas eu não sabia que incremento era tempo. Boa informação dbcc lock, parece ótimo. Você sabe quanto tempo essas informações estão disponíveis antes de serem despejadas no log de erros.
jesijesi
Desculpe, eu não me deixei claro. Eu estava perguntando, quanto tempo temos até executarmos o comando dbcc lock. Por exemplo, o bloqueio acontece e se eu executar o bloqueio dbcc após uma hora, ainda obteremos as informações?
jesijesi
@jesijesi - eu nunca tinha ouvido falar disso antes de hoje. Não tenho mais informações. Eu nem sei os parâmetros a serem passados ​​para desativá-lo. Mas você executa dbcc lock(StallReportThreshold, 200) primeiro e ele gera as informações quando o limite é excedido, desde que o sinalizador de rastreamento 3605 esteja ativado. O SQL Server não coleta essas informações para o caso de você poder executá-las posteriormente.
Martin Smith
2
Obrigado. basta adicionar um link que tenha uma função útil para converter os valores de resource_0,1,2 em xevents. sqlnotes.info/2011/10/24/…
jesijesi
5

Se você estiver interessado em bloquear, há vários eventos estendidos disponíveis:

lock_acquired
lock_released
lock_escalation

Os dois primeiros eventos têm uma durationcoluna (microssegundos) na qual você pode filtrar seus limites. Eles também têm uma resource_descriptionação que fornecerá alguns detalhes sobre os recursos envolvidos.

O lock_escalationevento também possui uma statementação que você pode adicionar para coletar a instrução T-SQL que acionou a escalação do bloqueio. Também tem escalation_cause. Aqui está uma sessão de amostra:

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

Eu suspeito que provavelmente haja um motivo para você não definir o limite do relatório de processo bloqueado para menos de um segundo: o bloqueio é perfeitamente normal em um RDBMS - o mecanismo de banco de dados precisa bloquear recursos para protegê-los. Embora não exista uma definição oficial de quando o bloqueio se torna bloqueado, o bloqueio do tique por mais de um segundo parece normal para mim.

wBob
fonte
1
o bloqueio se torna bloqueado assim que outra pessoa recebe acesso negado ao recurso e precisa aguardar devido ao bloqueio.
Martin Smith
Obrigado, estou planejando usar lock_acquired com o campo duration.
jesijesi
Boa sorte. Como você está no SQL Server 2014, você pode usar tabelas OLTP na memória com procs armazenados compilados nativamente, oferecendo uma opção sem trava de alto desempenho. Você também pode observar o isolamento de instantâneo.
WBob