주식회사 누리아이티

정보자산의 보안강화를 위한 3단계 인증 보안SW(BaroPAM) 전문기업인 누리아이티

▶ Tuxedo/오류 메시지(Oracle)

ORA-1591(Pending Transaction의 처리)

누리아이티 2010. 7. 6. 13:27

현상 : ORA-1591(Pending Transaction의 처리)
 

원인 : 분산 트랜잭션의 경우 2 phase commit수행 단계중에 fail이 발생하게 되면 관여된 일부 database에서는 rollback 혹은 commit이 되고, 일부는 distributed lock이 걸린 상태로 계속 지속될 수 있다.
         이렇게 pending된 transaction에 대해서는 기본적으로 Oracle의 background process인 RECO process가 자동으로 정리하여 주나, 경우에 따라 자동으로 정리가 되지 못하는 상황이 발생
 

조치 : STEP 1: alert.log file을 check한다.
         STEP 2: network 환경을 확인한다.
         STEP 3: RECO process가 떠 있는지 확인한다.
         STEP 4: DBA_2PC_PENDING을 조회해 본다.
         STEP 5: DBA_2PC_NEIGHBORS view를 조회해 본다.
         STEP 6: commit point site를 확인한다.
         STEP 7: DBA_2PC_PENDING의 MIXED column을 확인한다.
         STEP 8: DBA_2PC_PENDING의 STATE column의 값을 확인한다.
         STEP 9: 불일치 사항을 파악하고 DBA_2PC_PENDING을 정리한다.

         2PC에서 1st phase commit(xa_prepare)이 정상적으로 종료되면 Oracle의 dba_pending_transactions에 해당
         Transaction에 대한 정보가 나타난다.

         formatid  40
         globalid  636861656A750000000000000000000000000000000000
                   5B5103A6BEC9900000DE8
         branchid  0000006600000065

         이 상태에서 일정한 시간 내에 2nd phase commit(xa_commit)에 끝나지 않으면 dba_2pc_pending에도 이
         Transaction이 나타난다.

         local_tran_id     4.24.3026
         global_tran_id    40.636861656A750000000000000000000000000000000000
                           5B5103A6BEC9900000DE8
         state             prepared
         mixed             no
         advice
         tran_comment
         fail_time
         force_time
         retry_time
         os_user           jun
         os_termina
         host              chaeju
         db_user
         commit#           5332231

         위에서 "일정한 시간"이란 용어를 사용했는데 Oracle의 문서에는 이에 관한 정확한 언급은 없다.
         다만, 다른 Transaction에서 해당 레코드를 참조하려고 할 때 이미 lock이 걸려 있으므로 대기하는
         시간에 대해서는 init.ora에서 지정하는 distributed_lock_timeout에 대해서만 언급하고 있다. 그런데
         oracle 8.1.7에서는 distributed_lock_timeout을 설정하면 obsolete로 나온다.

         이 시간 동안에 해당 레코드에 대한 lock이 풀리지 않으면 아래와 같은 에러를 만난다.

         ORA-02049: time-out: distributed transaction waiting for lock

         위의 에러가 발생한 이후에 이 레코드를 참조하려고 하면 1591 에러가 나타난다.

         ORA-01591: lock held by in-doubt distributed transaction '4.24.3026'

         보는 것처럼 ORA-01591 에러 메시지에는 local_tran_id가 있다. 이를 이용하여 dba_2pc_pending에서
         global_tran_id를 조회하고, 이 데이터는 dba_pending_transaction의 formatid와 globalid로 이루어져
         있으므로 이를 이용하여 dba_pending_transaction에서 branchid도 얻을 수 있다.

         이들로 부타 아래와 같이 XID를 얻을 수 있다.

         xid.formatid = dba_pending_transactions.formatid
         xid.gtrid_length = len(dba_pending_transactions.globalid)
         xid.bqual_length = len(dba_pending_transactions.branchid)
         xid.data = dba_pending_transactions.globalid + dba_pending_transactions.branchid

         여기까지는 Oracle로 부터 XID를 얻는 과정이다.

         tpconvert(str, (char *)&xid, TPTOSTRING | TPCONVXID)를 이용하여 XID의 string 표현을 얻을 수 있고
         이값을 이용하여 .TMIB 서비스를 호출하면 아래와 같은 정보를 얻을 수 있다.

         TA_ERROR         0
         TA_MORE          0
         TA_OCCURS        1
         TA_GRPCOUNT      2
         TA_GRPINDEX      0
         TA_GRPNO         102
         TA_GRPNO         101
         TA_TIMEOUT       9
         TA_COORDGRPNO    102
         TA_CLASS         T_TRANSACTION
         TA_STATE         READY
         TA_COORDLMID     SITE1
         TA_GSTATE        READY
         TA_GSTATE        READY
         TA_TPTRANID      0x0 0x3a6bec99 0xde8 0x28 0x0 0x0
         TA_XID           0x0 0x3a6bec99 0xde8 0x28 0x66
         TA_COORDSRVGRP   APPGRP2
         TA_LMID          SITE1
         TA_SRVGRP        APPGRP2
         TA_SRVGRP        APPGRP1

         위의 경우에는 아직 Tuxedo가 transaction에 대한 정보를 가지고 있기 때문에 별다른 조치가 필요없다.
         하지만, Oracle의 dba_2pc_pending에는 있는데 Tuxedo에서 해당 Transaction에 대한 정보를 가지고
         있지 않은 경우에는 Oracle에서 rollback force나 commit force를 이용하여 pending transaction을
         정리해 주어야만 lock이 풀린다.