Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #59 da revista programar. Faz já o download aqui!

bronckhorst

Deadlock em UPDATE TABLE

Mensagens Recomendadas

bronckhorst    0
bronckhorst

Boa tarde.

 

Em algumas ocasiões, a minha aplicação origina mensagens de erro do tipo "Transaction (Process ID 52) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction."

Estes erros ocorrem principalmente em comandos UPDATE, como por exemplo:

UPDATE TOP (1) PRO.GeometriasCortadas SET status = 'T', mesatriagem = 'ert135', datatriagem = '2016-09-06 21:51:32' WHERE id_geometria = '157' AND codigoMP = 'AAV01CN0101' AND loteMP = 'A20942_9QH' AND subloteMP = '14998' AND status = 'C' AND IDCorteMeiasPeles <> '0'

Conseguem dizer-me alguma forma de corrigir esta situação?

Obrigado.

Carlos Araújo.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
M6    107
M6

Tipicamente é por processo concorrencial em escrita sobre a tabela, mas sem mais informação é impossível de dizer.

Podes começar por uma abordagem simples usando "with (rowlock)" no comando de update, forçando assim o lock apenas aos registos que vão ser atualizados e não à tabela.

A abordagem menos simples é colocares o update isolado numa transação.

A abordagem "correta" é analisares se é possível teres ai uma execução de código que tente, concorrencialmente, fazer lock aos mesmos registos mais de uma vez. Esqueci-me de referir que se te for possível, usa o profiler para ver o que se está a passar na base de dados e tentar perceber quem está a aceder a essa tabela e em que condições o faz.

Editado por M6
Esqueci-me de referir o profiler.
  • Voto 1

10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
jsWizard    6
jsWizard

Um deadlock ocorre quando A espera por B e B espera por A.

Exemplo: a tabela A tem um trigger que faz um update na tabela B e por sua vez a tabela B tem tb um trigger que faz update na tabela A.

Ora, neste caso, pode ocorrer um deadlock se o(s) registos estiverem locked, a base de dados vai esperar X tempo e depois opta por matar a transacção.

Este é um exemplo de má programação.

Deadlocks podem tb ocorrer sem ser por má programação (evidente.. como no exemplo anterior).. pode uma transacção (T1) estar a fazer um lock X e outra transacção (T2) estar a fazer um lock Y. Se T1 necessita de alterar Y vai esperar que Y seja libertado.. mas se T2 necessita de alterar X, vai tb esperar.. e novamente temos um deadlock.

É preciso ter atenção a referências circulares para evitar deadlock.. se for uma bd com muitos users em simultâneo.. pior ainda ;)

 

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bronckhorst    0
bronckhorst
Em 07/09/2016 às 15:07, M6 disse:

Tipicamente é por processo concorrencial em escrita sobre a tabela, mas sem mais informação é impossível de dizer.

Podes começar por uma abordagem simples usando "with (rowlock)" no comando de update, forçando assim o lock apenas aos registos que vão ser atualizados e não à tabela.

A abordagem menos simples é colocares o update isolado numa transação.

A abordagem "correta" é analisares se é possível teres ai uma execução de código que tente, concorrencialmente, fazer lock aos mesmos registos mais de uma vez. Esqueci-me de referir que se te for possível, usa o profiler para ver o que se está a passar na base de dados e tentar perceber quem está a aceder a essa tabela e em que condições o faz.

Obrigado pela resposta, M6.

Tentei usar a designação "with (rowlock)" no update, mas continuo a receber mensagens de erro do mesmo género.

Quando falas em colocar o update isolado numa transação, o que queres dizer com isso em concreto?

Obrigado pela ajuda.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
M6    107
M6

Refiro-me a colocares todo o código SQL que estás a executar numa transação.

Muito provavelmente esse update não é isolado, ocorre no meio de um conjunto de outras instruções de SQL. Todas essas instruções devem ser incluidas numa transação.

Talvez seja boa ideia meteres o profiler a ver o que se está a passar, para veres de onde vêm e como chegam os pedidos de update para despistares o que está a acontecer.


10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bronckhorst    0
bronckhorst

Bom dia.

Através do SQL Profiler, descobri qual era o outro comando UPDATE que estava a originar o DEADLOCK com este UPDATE que referi. Usando WITH (ROWLOCK) em ambos os UPDATES,parece que consegui evitar o DEADLOCK... Pelo menos, não recebi mensagens de erro do género nos últimos dias.

Muito obrigado pela vossa ajuda. 

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
M6    107
M6

Porreiro.

No entanto, uma vez que já descobriste qual o conflito, aconselho-te a usares transações em ambos, desta forma garantes que não haverá dead locks quando ambos os comandos tentarem guardar a mesma linha simultaneamente.quais o


10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.