enq : TX-row lock 경합 문제를 해결하는 방법은 무엇입니까?


9

다음과 같은 상황이 있습니다.

RAC가 있습니다. 두 노드 모두에 잠금이 있습니다.

첫 번째 노드에서

    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

세션 정보 차단

    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

두 번째 노드에서

    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

세션 정보 차단

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

추가 정보 : 차단 세션 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;

이 문제를 어떻게 해결합니까?

보시다시피 차단 세션은 비활성이지만 여전히 잠금 상태입니다.

나는 경우 select v$sql_bind_capture에 대한 가치가없는 VALUE_STRING세션을 차단 sql_id.

어디서부터 시작해야합니까?

커밋 / 롤백이 누락 된 것으로 추측 할 수 있지만 응용 프로그램 개발자는 "모든 것이 정상이며 필요한 곳에 커밋을 작성했습니다"라고 말합니다.

도와주세요.

답변:


6

v$transaction커밋되지 않은 세션을 보려면 각 노드에서 쿼리 하십시오.

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;

5

당신은 행이 미리와 업데이트를 사용할 수 있는지 확인하여 행 잠금 경합을 피할 수 있습니다 SELECT FOR UPDATE및 중 하나 WAIT X또는 NOWAIT, 예를 들면 :

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;

행이 잠겨 있으면 대부분의 경우 무한 대기보다 선호되는 ORA-00054를 받게됩니다.


0

보다 우아하고 안전한 업데이트 건너 뛰기 선택을 사용할 수 있습니다.


귀하의 답변이 정확한지 아닌지를 알 수있는 문제에 대해 충분히 알지 못합니다. 그러나 조금 짧습니다. 다른 것을 살펴보십시오. 여기에 대한 답변에는 일종의 확장과 함께 문서에 대한 링크가 수반되어야합니다! Jon Skeet (StackExchange에서 1M 포인트 이상)의 질문에 대한 사용법에 대한 링크가 하나 있습니다. 아마도 그것을보고 힌트를 따르고 싶습니까? ps 포럼에 오신 것을 환영합니다! :-)
Vérace 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.