Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

wallter

ORA-00060: deadlock detected while waiting for resource

Recommended Posts

Bom dia

 

Estou com problema e não consigo resolver. Criei uma trigger para monitorar uma tabela de pedidos, quando acontece o insert, ela deleta os registro inserido e insere os novos. Então minha trigger monitora e faz o insert na mesma tabela. Estou erro de deadlock, quando tento fazer qualquer insert nesta tabela.

A primeira parte da trigger verifica verifica se pedido existe em uma outra tabela, se existir a trigger executa.

CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE
AFTER
INSERT OR DELETE OR UPDATE
ON APROV_PED_SUP
FOR EACH ROW

DECLARE
  existe_registro  NUMBER(1);
  Pragma Autonomous_Transaction;

BEGIN


IF INSERTING THEN


   BEGIN
   SELECT 1
  into existe_registro
  from VI_VERIFICA_PEDIDO_ESTOQUE
  where num_pedido = :NEW.NUM_PEDIDO;
  
   EXCEPTION
                 WHEN OTHERS THEN
    existe_registro := 0;
   END;

  if existe_registro = 1  THEN


DELETE FROM  APROV_PED_SUP WHERE NUM_PEDIDO = :NEW.NUM_PEDIDO
                           AND NUM_VERSAO_PEDIDO = :NEW.NUM_VERSAO_PEDIDO;


BEGIN
INSERT INTO APROV_PED_SUP

SELECT A.COD_EMPRESA,
       B.NIVEL,
       A.NUM_PEDIDO,
       A.NUM_VERSAO,
       1 VERSAO_GRADE,
       CASE WHEN B.NIVEL ='CO' THEN D.LOGIN ELSE NULL END NOME_USUARIO_APROV,
       CASE WHEN B.NIVEL ='CO' THEN TO_DATE(SYSDATE,'DD/MM/YYYY') ELSE NULL END  DATA_APROVACAO,
       CASE WHEN B.NIVEL ='CO' THEN TO_CHAR(SYSDATE,'HH24:MI:SS') ELSE NULL END  HOR_APROVACAO,
       D.LOGIN USUARIO_INCLUSAO,
       TO_DATE(SYSDATE,'DD/MM/YYYY') DAT_INCLUSAO,
       TO_CHAR(SYSDATE,'HH24:MI:SS') HOR_INCLUSAO
      
FROM PEDIDO_SUP A INNER JOIN GRADE_ESTOQUE B
                  ON(A.VAL_TOT_PED >= B.VALOR_INI
                     AND A.VAL_TOT_PED <= B.VALOR_FIM)
                  INNER JOIN ORDEM_SUP C
                  ON(A.NUM_PEDIDO = C.NUM_PEDIDO)
                  INNER JOIN COMPRADOR D
                  ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01)
WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO
      AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO
      
      GROUP BY   A.COD_EMPRESA,
                 B.NIVEL,
                 A.NUM_PEDIDO,
                 A.NUM_VERSAO,                
                 D.LOGIN;
               
                 END;
   END IF;
   END IF;
 END;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Despulpe mas qual seria a razão deste processo ?

 

Você poderia obter valores por query e atribuí-los aos campos da tabela da trigger , mas a trigger teria de ser de BEFORE.

 

Mas o processo me parece estranho , deletar para depois inserir.

 

Outra observação : se só vai tratar o INSERT a trigger só precisa ser de INSERT

-----

Ficaria algo assim

CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE
BEFORE
INSERT
ON APROV_PED_SUP
FOR EACH ROW

DECLARE
  existe_registro  NUMBER(1);
  Pragma Autonomous_Transaction;
 
  --defina aqui as variaveis
  VS_COD_EMPRESA PEDIDO_SUP.COD_EMPRESA%type;
    VS_NIVEL   tipo etc
    VS_NUM_PEDIDO tipo etc
    VS_NUM_VERSAO tipo etc
    VS_VERSAO_GRADE tipo etc
    VS_NOME_USUARIO_APROV tipo etc
    VS_DATA_APROVACAO tipo etc
    VS_HOR_APROVACAO tipo etc
    VS_USUARIO_INCLUSAO tipo etc
    VS_DAT_INCLUSAO tipo etc
    VS_HOR_INCLUSAO tipo etc

BEGIN


IF INSERTING THEN


   BEGIN
   SELECT 1
  into existe_registro
  from VI_VERIFICA_PEDIDO_ESTOQUE
  where num_pedido = :NEW.NUM_PEDIDO;
 
   EXCEPTION
                 WHEN OTHERS THEN
    existe_registro := 0;
   END;

  if existe_registro = 1  THEN




BEGIN

SELECT A.COD_EMPRESA,
       B.NIVEL,
       A.NUM_PEDIDO,
       A.NUM_VERSAO,
       1 VERSAO_GRADE,
       CASE WHEN B.NIVEL ='CO' THEN D.LOGIN ELSE NULL END NOME_USUARIO_APROV,
       CASE WHEN B.NIVEL ='CO' THEN TO_DATE(SYSDATE,'DD/MM/YYYY') ELSE NULL END  DATA_APROVACAO,
       CASE WHEN B.NIVEL ='CO' THEN TO_CHAR(SYSDATE,'HH24:MI:SS') ELSE NULL END  HOR_APROVACAO,
       D.LOGIN USUARIO_INCLUSAO,
       TO_DATE(SYSDATE,'DD/MM/YYYY') DAT_INCLUSAO,
       TO_CHAR(SYSDATE,'HH24:MI:SS') HOR_INCLUSAO
       INTO
       VS_COD_EMPRESA,
       VS_NIVEL,
       VS_NUM_PEDIDO,
       VS_NUM_VERSAO,
       VS_VERSAO_GRADE,
       VS_NOME_USUARIO_APROV,
       VS_DATA_APROVACAO,
       VS_HOR_APROVACAO,
       VS_USUARIO_INCLUSAO,
       VS_DAT_INCLUSAO,
       VS_HOR_INCLUSAO
      
FROM PEDIDO_SUP A INNER JOIN GRADE_ESTOQUE B
                  ON(A.VAL_TOT_PED >= B.VALOR_INI
                     AND A.VAL_TOT_PED <= B.VALOR_FIM)
                  INNER JOIN ORDEM_SUP C
                  ON(A.NUM_PEDIDO = C.NUM_PEDIDO)
                  INNER JOIN COMPRADOR D
                  ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01)
WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO
      AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO
      
      GROUP BY   A.COD_EMPRESA,
                 B.NIVEL,
                 A.NUM_PEDIDO,
                 A.NUM_VERSAO,                
                 D.LOGIN;
               
                 END;

atribui ao new

   :new.NUM_PEDIDO := vs_NUM_PEDIDO;
   demais campos   
                
   END IF;
   END IF;
 END;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia Motta

 

A razão é, contornar algo que aplicação não resolve para o momento. Aplicação faz o insert de 4 linhas, a trigger deleta as 4 e faz o insert de 3 linhas diferentes.

Acredito que a solução proposta por você só pode inserir uma linha correto?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que trigger não vai resolver isto pois se está deletando e inserindo na mesma tabelae um número de registros diferentes

 

Talvez , e digo talvez pois nunca fiz nada parecido uma TRIGGER de INSTEND OF resolva , mas só testando.

Mas para isto acho que a aplicação deveria trabalhar com uma trigger e não a tabela em si , o que pode ser um complicador.

 

O correto seria consertar a aplicação , é tão complicado assim !?

 

=======================================================

 

Outra solução seria uma procedure que faria esta correção um JOB schedullado rodando de x em x minutos faria a correção.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia Motta,

 

Consegui fazer uma alteração na aplicação, e agora a trigger só precisa excluir uma das três linhas que são inseridas.

Fiz a trigger, mas por algum motivo que não entendo ela não esta excluindo. Se rodo a query direto ela exclui a terceira linha perfeitamente, mas na trigger não vai.

CREATE OR REPLACE TRIGGER TG_GRADE_ESTOQUE_03
AFTER INSERT ON APROV_PED_SUP FOR EACH ROW

DECLARE   
 Pragma Autonomous_Transaction; 
 
cursor c1 is
select COD_NIVEL_AUTORID,
       NUM_PEDIDO,
       NUM_VERSAO_PEDIDO 
from LOGIX.APROV_PED_SUP
WHERE COD_NIVEL_AUTORID NOT IN (SELECT  B.NIVEL 
                  FROM LOGIX.PEDIDO_SUP A INNER JOIN LOGIX.GRADE_ESTOQUE B
                  ON(A.VAL_TOT_PED >= B.VALOR_INI
                  AND A.VAL_TOT_PED <= B.VALOR_FIM)
                  INNER JOIN LOGIX.ORDEM_SUP C
                  ON(A.NUM_PEDIDO = C.NUM_PEDIDO)
                  INNER JOIN LOGIX.COMPRADOR D
                  ON(C.COD_COMPRADOR = D.COD_COMPRADOR AND D.COD_EMPRESA =01)
WHERE A.NUM_PEDIDO =:NEW.NUM_PEDIDO
      AND A.NUM_VERSAO =:NEW.NUM_VERSAO_PEDIDO
      
      GROUP BY   A.COD_EMPRESA,
                 B.NIVEL,
                 A.NUM_PEDIDO,
                 A.NUM_VERSAO,                
                 D.LOGIN);
BEGIN

   for r1 in c1 loop        
    
   DELETE FROM LOGIX.APROV_PED_SUP WHERE NUM_PEDIDO = r1.NUM_PEDIDO
                           AND NUM_VERSAO_PEDIDO = r1.NUM_VERSAO_PEDIDO
                           AND COD_NIVEL_AUTORID = r1.COD_NIVEL_AUTORID; 
              COMMIT;  
        END LOOP; 
END;         

Compartilhar este post


Link para o post
Compartilhar em outros sites

Qual o problema em alterar a aplicação para não inserir as linhas indevidas ?

 

Por trigger , excluído a própria operação acho que não rola, mas só pesquisando.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.