¿Cómo solucionar problemas de enq: TX - contención de bloqueo de fila?

9

Tengo la siguiente situación.

Tengo RAC En ambos nodos están las cerraduras.

En el primer nodo

    SID EVENT                           USERNAME    BLOCKING_SESSION    ROW_WAIT_OBJ#   OBJECT_NAME LOCKWAIT            SQL_ID          STATUS
1   102 enq: TX - row lock contention   MYUSER      155                 136972          TABLE1V     0000000810EFA958    5f4bzdg49fdxq   ACTIVE
2   111 enq: TX - row lock contention   MYUSER      155                 136972          TABLE1V     0000000810EFAC98    5f4bzdg49fdxq   ACTIVE

Bloqueo de información de sesión

    SID EVENT                       USERNAME    ROW_WAIT_OBJ#   OBJECT_NAME LOCKWAIT    SQL_ID          STATUS
1   155 SQL*Net message from client MYUSER      136971          MyTABLEIMAGES_IDPK      4hw85z8absbjc   INACTIVE

En el segundo nodo

    SID EVENT                           USERNAME    BLOCKING_SESSION    ROW_WAIT_OBJ#   OBJECT_NAME   LOCKWAIT          SQL_ID          STATUS
1   65  enq: TX - row lock contention   MYUSER      155                 137033          FactTABLE1V   0000000810EF9B58  1mznc2z75ksdx   ACTIVE
2   111 enq: TX - row lock contention   MYUSER      155                 136972          TABLE1V       0000000810EF9818  5f4bzdg49fdxq   ACTIVE

Bloqueo de información de sesión

    SID EVENT                       USERNAME    ROW_WAIT_OBJ#   OBJECT_NAME  SQL_ID  STATUS
1   155 SQL*Net message from client MYUSER      127176          MYTableLOG           INACTIVE

Información adicional: sesión de bloqueo SQL_TEXT

create or replace procedure ACTIONProcedureDELETE
(
p_ID NUMBER
)
 is

 cursor oldval is select r.id,r.sessionstatus
  from MyTABLEIMAGES  r where r.idparent=p_ID;

begin
       update  actionmyTableblock r  set r.status='False' where  ID=p_ID;

   for oldvalItem in oldval loop

    if oldvalItem.Sessionstatus='True' then
      update MyTABLEIMAGES r set r.sessionstatus='False' where r.id=oldvalItem.Id;
    else
      update MyTABLEIMAGES r set r.sessionstatus='True' where r.id=oldvalItem.Id;
    end if;
  end loop;

end ACTIONProcedureDELETE;

¿Cómo soluciono esto?

Como puede ver, la sesión de bloqueo es INACTIVA pero sigue bloqueándose.

Si no select v$sql_bind_capturehay ningún valor VALUE_STRINGpara bloquear la sesión sql_id.

¿Por dónde empezar?

Puedo adivinar que faltan commit / rollback pero el desarrollador de la aplicación dice "Tengo todo bien, he escrito commit donde es necesario"

Por favor ayuda.

kupa
fuente

Respuestas:

6

Consulta v$transactionen cada nodo para ver sesiones no confirmadas:

SELECT t.start_time, s.sid, s.serial#, s.username, s.status,s.schemaname, s.osuser
   , s.process, s.machine, s.terminal, s.program, s.module
   , to_char(s.logon_time,'DD/MON/YY HH24:MI:SS') logon_time
FROM v$transaction t, v$session s
WHERE s.saddr = t.ses_addr
ORDER BY start_time;
Leigh Riffel
fuente
5

Puede evitar la contención de bloqueo de fila asegurándose de que la fila esté disponible para actualizar de antemano con un SELECT FOR UPDATEy WAIT Xo NOWAIT, por ejemplo:

create or replace procedure ACTIONProcedureDELETE (p_ID NUMBER)
 is

 cursor oldval is select r.id,r.sessionstatus
  from MyTABLEIMAGES  r where r.idparent=p_ID FOR UPDATE NOWAIT;

 l_id NUMBER;

begin
   select id into l_id from actionmyTableblock where ID=p_ID 
      FOR UPDATE of status NOWAIT;

   update  actionmyTableblock r  set r.status='False' where  ID=p_ID;

   for oldvalItem in oldval loop

    if oldvalItem.Sessionstatus='True' then
      update MyTABLEIMAGES r set r.sessionstatus='False' where r.id=oldvalItem.Id;
    else
      update MyTABLEIMAGES r set r.sessionstatus='True' where r.id=oldvalItem.Id;
    end if;
  end loop;

end ACTIONProcedureDELETE;

Si la fila está bloqueada, recibirá un ORA-00054 que en la mayoría de los casos es preferible a la espera indefinida.

Vincent Malgrat
fuente
0

puede usar la selección para actualizar la omisión bloqueada, que es más elegante y segura

kamal qoshtom
fuente
No sé lo suficiente sobre el problema para saber si su respuesta es correcta o no. Sin embargo, es un poco corto, eche un vistazo a los demás. ¡Las respuestas aquí deben ir acompañadas de una expansión de algún tipo y posiblemente enlaces a la documentación! Tengo un enlace a un tutorial sobre cómo responder preguntas de Jon Skeet (más de 1 millón de puntos en StackExchange). ¿Quizás le gustaría verlo e intentar seguir sus consejos? ps bienvenido al foro! :-)
Vérace