Jump to content

Recommended Posts

Posted

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.

Posted (edited)

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.

Edited by M6
Esqueci-me de referir o profiler.
  • Vote 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."

 

Posted

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 😉

  • 2 weeks later...
Posted
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.

Posted

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."

 

Posted

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. 

Posted

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."

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.