Quando vários procedimentos são bloqueados em um recurso compartilhado, como o sql server escolhe qual deles será retomado?
Exemplo 1
proc sp_a
begin tran
select 1 from dbo.lock_tbl with ( tbllockx )
delay wait for '00:00:01'
commit / rollback;
Executar
exec sp_a -- on terminal 1
exec sp_a -- on terminal 2
exec sp_a -- on terminal 3
O sql server escolhe se deseja iniciar a instância em 2 ou 3 primeiro?
Exemplo 2
Mais próximo do uso pretendido
proc sp_b @source_param
declare @rows cursor = ... get_rows( @source_param )
while ( ... for each @row )
begin
begin tran
select 1 from dbo.lock_tbl with ( tbllockx )
-- do logic
exec sp_g @row
commit / rollback;
delay wait for '00:00:01'
end
Executar
exec sp_b 'd' -- on terminal 1
exec sp_b 'e' -- on terminal 2
exec sp_b 'f' -- on terminal 3
O código acima do round-robin executará o procedimento sp_g de cada procedimento, por exemplo: ele executará sp_g no terminal 1, então executará sp_g no terminal 2, então executará sp_g no terminal 3, então executará g no terminal 1, etc?
Acompanhamentos :
Ele passa o bloqueio para o procedimento que está esperando há mais tempo?
Existe uma maneira de incentivar o comportamento round robin?
Justificativa
( opcional ) O banco de dados é um banco de dados de transações baixas, mas atingirá deadlocks quando várias transações ocorrerem ao mesmo tempo, devido à lógica de negócios de execução complexa. Uma tabela de bloqueio global pode ser usada para eliminar deadlocks por meio da limitação do fluxo de execução para um thread por vez. Manter a execução síncrona parece mais desejável do que reestruturar o banco de dados e a interface do usuário em filas assíncronas. O trabalho ocorrerá em pequenas transações e controle de procedimentos entre os procedimentos, que se revezarão para concluir seus respectivos trabalhos em partes, retardando assim a conclusão das tarefas em troca de conclusão síncrona confiável.
Exemplo 1: Você não deveria se importar. O processo é muito mais complicado do que parece, e acho que você não tem nenhuma garantia. Os 3 comandos vão para a fila em ordem. O primeiro é puxado e executado, quando o segundo é tentado, o mecanismo pode optar por colocá-lo de volta na fila se aguardar mais do que algum limite, e o terceiro pode ser puxado e tentado. se acontecer que os recursos agora estejam livres, o 3º será executado primeiro. caso contrário, ele pode voltar à fila novamente.
Exemplo 2: Acho que o acima explica isso, e a resposta para ambas as suas perguntas não é AFAIK, a menos que você desenvolva um buffer de execução próprio. Não.
Justificativa: Agora você chegou ao desafio principal, que deveria ser o título - "Como lidar com impasses". Você assumiu que sua solução de 'tabela de bloqueio global' é a única maneira de corrigir as coisas, mas acho que o preço de perder toda a simultaneidade não vale a pena. Seria mais fácil ter os procedimentos executados em série usando algum tipo de agendador. Você abrirá uma caixa de Pandora com essa abordagem que será difícil de fechar. Enfileirar e sincronizar é um desafio muito complicado.
Se eu estivesse no seu lugar, primeiro investigaria a causa raiz dos impasses. Às vezes, algo tão simples como adicionar ou modificar um índice pode resolvê-lo. Se você postar seus gráficos de deadlock aqui, junto com as consultas envolvidas com seus planos de execução, as pessoas o ajudarão a identificar a raiz do problema.
HTH