트랜잭션 교착 상태(deadlock)

교착 상태(deadlock)는 둘 이상의 트랜잭션이 서로 맞물려 상대방의 잠금이 해제되기를 기다리는 상태이다. 이러한 교착 상태에서는 서로가 상대방의 작업 수행을 차단하기 때문에 CUBRID는 트랜잭션 중 하나를 롤백시켜 교착 상태를 해결한다. 롤백되는 트랜잭션은 일반적으로 가장 적은 갱신을 수행한 것인데 보통 가장 최근에 시작된 트랜잭션이다. 시스템에 의해 트랜잭션이 롤백되자마자 그 트랜잭션이 가지고 있던 잠금이 해제되고 교착 상태에 있던 다른 트랜잭션이 진행되도록 허가된다.

이러한 교착 상태 발생은 예측할 수 없지만 가급적 교착 상태가 발생하지 않도록 하려면, 인덱스를 설정하여 잠금이 설정되는 범위를 줄이거나 트랜잭션을 짧게 만들거나 트랜잭션 격리 수준(isolation level)을 낮게 설정하는 것이 좋다.

에러 심각성 수준을 설정하는 시스템 파라미터인 error_log_level의 값을 NOTIFICATION으로 설정하면 교착 상태 발생 시 서버 에러 로그 파일에 잠금 관련 정보가 기록된다.

다음의 에러 로그 파일 정보에서 (1)은 교착상태를 유발한 테이블 이름을, (2)는 인덱스 이름을 나타낸다.

demodb_20111102_1811.err

    ...

    OID = -532| 520| 1

(1) Object type: Index key of class ( 0| 417| 7) = tbl.

    BTID = 0| 123| 530

(2) Index Name : i_tbl_col1

    Total mode of holders = NS_LOCK, Total mode of waiters = NULL_LOCK.

    Num holders= 1, Num blocked-holders= 0, Num waiters= 0

    LOCK HOLDERS:

    Tran_index = 2, Granted_mode = NS_LOCK, Count = 1

...

예제

session 1

session 2

;autocommit off

AUTOCOMMIT IS OFF

set transaction isolation level 6;

Isolation level set to:

SERIALIZABLE

;autocommit off

AUTOCOMMIT IS OFF

set transaction isolation level 6;

Isolation level set to:

SERIALIZABLE

CREATE TABLE lock_tbl(host_year integer, nation_code char(3));

INSERT INTO lock_tbl VALUES (2004, 'KOR');

INSERT INTO lock_tbl VALUES (2004, 'USA');

INSERT INTO lock_tbl VALUES (2004, 'GER');

INSERT INTO lock_tbl VALUES (2008, 'GER');

COMMIT;

 

SELECT * FROM lock_tbl;

    host_year  nation_code

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

         2004  'KOR'

         2004  'USA'

         2004  'GER'

         2008  'GER'

 

 

SELECT * FROM lock_tbl;

    host_year  nation_code

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

         2004  'KOR'

         2004  'USA'

         2004  'GER'

         2008  'GER'

DELETE FROM lock_tbl WHERE host_year=2008;

 

/* no result until transaction 2 releases a lock

 

C:\CUBRID>cubrid lockdb demodb

*** Lock Table Dump ***

 

Object type: Class = lock_tbl.

LOCK HOLDERS:

    Tran_index =   2, Granted_mode =   S_LOCK, Count =   2, Nsubgranules =  0

 

BLOCKED LOCK HOLDERS:

    Tran_index =   1, Granted_mode =   S_LOCK, Count =   3, Nsubgranules =  0

    Blocked_mode = SIX_LOCK

    Start_waiting_at = Fri Feb 12 14:22:58 2010

    Wait_for_nsecs = -1

 

*/

 

 

INSERT INTO lock_tbl VALUES (2004, 'AUS');

ERROR: Your transaction (index 1, dba@ 090205|4760) has been unilaterally aborted by the system.

 

/*

System rolled back the transaction 1 to resolve a deadlock

 

C:\CUBRID>cubrid lockdb demodb

*** Lock Table Dump ***

 

Object type: Class = lock_tbl.

 

LOCK HOLDERS:

    Tran_index =   2, Granted_mode = SIX_LOCK, Count =   3, Nsubgranules =  0

*/