본문 바로가기

카테고리 없음

ORACLE 9i lock type ( TX 편 ) v1.0

from Practical OWI | exem | exem

lock type - tx

 

tx ROW에 대해 걸리는 LOCK 이다.

 

TX Lock 경합 발생 원인으로

 

동일 Row 변경

Unique Key 충돌

ITL Entry 부족

Bitmap Index

Index Leaf Node Split

기타 등의 이유가 있다.

 

테스트는 9i 에서 확인하였다. v$lock 9i에도 있다. ( v$lock_type 10g에만 있다. )

/*+ 9i 10g 비교 해 볼 것 */

각각의 예를 보기 전에 필요한 view 에 대해 이야기 하고자 한다. tx 락 경합발생 확인을 위해 v$lock view를 사용할 것이며 아래와 같은 쿼리를 사용할 것이다.

 

SQL> get w_cur_lck

  1  select sid,type,id1,id2,lmode,request,ctime,block

  2  from v$lock

3* where type in ( 'TX', 'TM')

 

lock type TX TM 인 경우를 찾는 쿼리이다.

 

 

동일 Row 변경

 

SESSION #1 (SCOTT)

 

SQL> update emp set sal=1111 where empno=7788;

 

1 row updated.

 

SESSION #2 (SCOTT)

 

SQL> update emp set sal=9999 where empno=7788;

 

(SESSION#1 KILL 하거나 COMMIT/ROLLBACK 할때까지 대기상태에 빠진다.)

 

SESSION #3 (SYS)

 

SQL> get w_cur_lck

  1  select sid,type,id1,id2,lmode,request,ctime,block

  2  from v$lock

3* where type in ( 'TX', 'TM')

 

SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------- -- ---------- ---------- ---------- ---------- ---------- ----------

        14 TX     196621       2609          6          0         71          1

        14 TM       6432          0          3          0         71          0

        16 TM       6432          0          3          0          1          0

        16 TX     196621       2609          0          6          1          0

 

LMODE 컬럼은 LOCK MODE를 의미한다

  • 0 - none
  • 1 - null (NULL)
  • 2 - row-S (SS)
  • 3 - row-X (SX)
  • 4 - share (S)
  • 5 - S/Row-X (SSX)
  • 6 - exclusive (X)

REQUEST의 숫자도 위의 정보를 의미하며 이는 해당 세션이 숫자에 해당하는 모드로 LOCK을 획득하려 한다는 의미이다.

 

위에서 SID 14인 세션은 TX LOCK EXCLUSIVE 하게 획득하였다. 반대로 SID 16일 세션은 TX LOCK EXCLUSIVE 하게 획득하려 한다. ( REQUEST )

 

CTIME은 현재 상태를 가진 이래로 지난 시간을 의미한다. (쿼리를 반복실행 한 결과 단위는 인 듯 하다. )

 

BLOCK 값의 1은 해당 LOCK이 다른 LOCK을 차단하고 있다는 것을 의미한다. (LOCK HOLDER)

 

 

Unique Key 충돌

 

전제 : insert 의 타겟이 되는 컬럼에 unique 키 조건이 설정되어 있어야 한다.

 

Session #1

 

SQL> insert into emp(empno) values(8899);

 

1 row created.

 

Session #2

 

SQL> insert into emp(empno) values(8899);

 

(대기상태에 빠짐…)

 

SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------- -- ---------- ---------- ---------- ---------- ---------- ----------

         9 TX      65541       2097          6          0         31          0

         9 TM       6432          0          3          0         31          0

         9 TX     524306       1905          0          4         31          0

        10 TX     524306       1905          6          0         62          1

        10 TM       6432          0          3          0         62          0

 

SID 9 인 세션이 EXCLUSIVE TX EXCLUSIVE(6) 로 획득하였다. SID 10인 세션이 TX락을 SHARED 획득하려 함

SID 9 인 세션은 아직 TRANSACTION 이 종료 (COMMIT/ROLLBACK) 되지 않았기 때문에 이에 접근하는 타 세션은 대기하게 된다.

위 상태에서 Rollback 하면 대기하던 세션의 트랜잭션이 성공하고 반대로 commit 하면 unique 키 제약조건에 위배된다는 에러 메시지를 볼 수 있다.

 

Session #1 ( commit 의 경우 )

 

SQL> insert into emp(empno) values(8899);

 

1 row created.

<< Session #2 대기상태 >>

SQL> commit;

 

Commit complete.

 

Session #2 ( rollback 의 경우 )

 

SQL> insert into emp(empno) values(8899);

insert into emp(empno) values(8899)

<<대기상태>>

ERROR at line 1:

ORA-00001: unique constraint (SCOTT.EMP_EMPNO_UK_IDX) violated

 

 

ITL Entry 부족

 

SQL> select table_name, ini_trans, max_trans

  2  from user_tables;

 

TABLE_NAME                      INI_TRANS  MAX_TRANS

------------------------------ ---------- ----------

BONUS                                   1        255

DEPT                                    1        255

DUMMY                                   1        255

EMP                                     1        255

SALGRADE                                1        255

 

maxtrans 값을 낮춰준다.

 

SQL> alter table emp maxtrans 2;

 

Table altered.

 

maxtrans 값은 ITL 엔트리 수와 관계있다. 이를 할당 받지 못하면 DML 수행이 대기상태에 빠진다. ITL ( Interested Transaction List ) BLOCK을 변경하고자 하는 Transaction 목록을 가지고 있으며 DML 트랜잭션은 블록을 변경하기 전 ITL 에 엔트리를 등록해야 한다.

 

/*+ INITRANS MAXTRANS ITL 의 정확한 관계에 대해서… */

 

Session #1 ( USER )

 

SQL> update emp set ename='hello' where empno=1;

 

1 row updated.

 

Session #2 ( USER )

 

SQL> update emp set ename='hello' where empno=2;

 

1 row updated.

 

Session #3 ( USER )

 

SQL> update emp set ename='hello' where empno=1;

 

(대기상태에 빠짐)

 

Session #4 (SYS)

 

SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------- -- ---------- ---------- ---------- ---------- ---------- ----------

         9 TX     393220       3826          6          0         23          0

         9 TM       6432          0          3          0         23          0

        10 TX     131081       2085          6          0         31          1

        10 TM       6432          0          3          0         31          0

        12 TM       6432          0          3          0         19          0

        12 TX     131081       2085          0          4         15          0

 

SID 9,10 에 해당하는 SESSION TX락을 EXCLUSIVE 하게 잡았고 이후 12번이 TX SHARE 모드로 요청하였으나 WAIT 에 빠지게 된다. BLOCKER SID 10번의 SESSION 으로 나온다. 사실 10 뿐만 아니라 9번도 ITL 블록을 잡고 있기 때문에 BLOCKING 에 영향을 주고 있다.

 

해결안으로써 INITRANS 을 높이고 MAXTRANS 값을 낮추지 말 것 마지막으로 ROW MIGRATION ROW CHAINING 수치를 낮출 것 등이다. 후자의 경우 하나의 ROW UPDATE에 여러 블록의 ITL ENTRY를 할당하기 때문에 경합이 발생할 확률이 높아진다.

MAXTRANS 값의 경우 10g에서 255로 정해져있다. ( ALTER 명령으로 변경가능 )

 

위 상태 ( initrans 1, maxtrans 2, session 1, 2, 3 dml 실행 session 3 대기상태 ) 에서 3번 세션을 제외한 세션에서 commit 이나 rollback 을 수행하면 wait 상태였던 3번 세션이 작업을 다시수행하게 된다.

 

 

Bitmap Index

 

샘플 세그먼트를 만들겠다. GENDER 값을 (1, 0, 1, 0, …  번갈아 가지게 하였다.)

 

SQL> create table bit     

  2  (id number,

  3  gender number);

 

Table created.

 

SQL> begin    

  2     for i in 1..1000 loop

  3             insert into bit(id) values(i);

  4     end loop;

  5  end;

  6  /

 

PL/SQL procedure successfully completed.

 

SQL> update bit set gender = 1;

 

1000 rows updated.

 

SQL> begin

  2     for i in 1..500 loop

  3             update bit set gender=0 where id = (i * 2);

  4     end loop;

  5  end;

6  /

 

PL/SQL procedure successfully completed.

 

SQL> create bitmap index bit_gender_bidx on bit(gender);

 

Index created.

 

Session #1 ( USER )

 

SQL> update bit set gender = 0 where id = 1;

 

1 row updated.

 

Session #2 ( USER )

 

SQL> update bit set gender = 0 where id = 3;

(대기 상태로 빠짐)

 

Session #3 ( SYS )

 

SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK

---------- -- ---------- ---------- ---------- ---------- ---------- ----------

        10 TX     131082       2073          6          0         12          0

        10 TM       6460          0          3          0         12          0

        10 TX      65554       2097          0          4         12          0

        16 TX      65554       2097          6          0         55          1

        16 TM       6460          0          3          0         55          0

 

SID 16번인 세션이 BLOCKER 이다. TX LOCK EXCLUSIVE로 획득하였고 후에 10번인 세션이 TX LOCK SHARE로 요구하였다. 이미 EXCLUSIVE LOCK이 잡혀있기 때문에 SHARE 모드는 대기할 수밖에 없으며 이는 16번 세션이 트랜잭션을 종료(COMMIT , ROLLBACK)하기 전까지 지속된다. 이와 같은 증상이 나타나는 이유는 BITMAP INDEX LEAF 노드가 COLUMN 값 뿐만 아니라 비트맵과 START ROWID ~ END ROWID 값을 가지기 때문이다. ROW에 변경 ( 비트맵을 사용하는 해당컬럼 ) 이 일어나면 리프노드의 비트맵을 매번 새로 계산해주어야 한다. 이때 TX락을 획득하게 되어 이후 오는 트랜잭션들은 대기하게 된다.

 

 

Index Leaf Node Split

 

Index leaf Node split 이 발생시 다른 프로세스는 완료시까지 대기상태

 

 /*+ 아직 샘플을 만들지 못했음 */

/*+ split 에 대한 이야기 */