DML 이 수행되는 동안, DML과 관련된 객체에 대한 변경을 방지하기 위해 DML을 수행하는 프로세스는 반드시 해당 테이블에 대해 TM 락을 획득해야 한다. *TM 락을 획득하는 과정에서 경합이 발생하면 enq: TM - contention 이벤트 대기
일반적인 DML문은 테이블에 대해 TM 락을 Sub-Exclusive(SX) 모드로 획득한다. Sub-Exclusive 모드간에는 상호 호환성이 있기 때문에 여러 세션이 동일 테이블에 대해 동시에 DML 수행이 가능하다.
DML을 수행한 세션은 테이블에 대해서는 TM락을 Sub-Exclusive 모드로 획득하고, 변경된 데이터에 대해서는 TX 락을 Exclusive 모드로 획득한다.
Oracle Reference Manual의 Lock
DML 락 : Data Lock. DML 수행시 데이터를 보호하기 위한 락. 로우 락(TX)은 특정 로우를 보호하고, 테이블 락™은 전체 테이블을 보호한다. DBA_DML_LOCKS 를 통해 관찰 가능하다. DBA_DML_LOCKS은 V$LOCK 뷰에서 락 유형이 TM 인것만을 추출 한 것 DML_LOCKS : 데이터베이스(인스턴스)에서 허용 가능한 TM 락 개수(자동 셋팅됨) DML_LOCKS = 0 : TM 락 획득 필요하지 않고, 테이블에 대한 DDL 원천적 불가
DDL 락 : Data Dictionary lock. User/Table/View/Procedure 등의 정의를 보호한다. DBA_DDL_LOCKS 를 통해 관찰 가능하다.
Internal locks and latches
h2.TM LOCK 경합이 발생하는 경우
인덱스가 없는 Foreign Key 의 부모키를 변경하는 경우
DML과 DDL 간의 TM 락 경합
LOCK TABLE ... 에 의한 TM 락 경합
Direct load 작업에 의한 TM 락 경합
인덱스가 없는 Foreign Key
9i 이전에는 인덱스가 없는 Foreign Key 컬럼이 TM 락 경합의 주된 원인
9i 이전에서는 자식 테이블의 Foreign key 컬럼에 인덱스가 없는 상태에서 부모 테이블의 Key가 변경되면, 자식 테이블에 대해 Shared 모드나 Shared-Sub-Exclusive 모드로 TM 락은 획득 해야 했다. 획득한 TM 락은 부모 Key 를 변경한 트랜잭션이 종료(commit 또는 Rollback) 될 때까지 유지됨
9i 이후부터는 알고리즘 개선으로 상기와 같은 문제 발생하지 않는다.
9i 이전 버전 사용시에는, Foreign key 칼럼에 반드시 인덱스 생성한다.
h2.부적절한 DDL로 인한 TM 락 경합
트랜잭션이 진행중인 테이블에 대해서는 기본적으로 DDL이 불가능하다.
반면, DDL이 수행중인 테이블에 대해서 DML을 수행하는 경우에는 TM 락 경합이 발생할 수 있다.
특정 프로세스가 테이블에 대해서 인덱스를 생성하는 경우, 인덱스가 생성되는 동안에는 테이블에 대해서 TM 락을 Shared 모드로 획득
데이터 량이 많은 테이블에 대한 부적절한 DDL을 수행하게 되면, 해당 테이블을 접근하는 모든 DML 세션이 대기상태에 빠지게 되고, 장애 상황으로까지 발전할 수 있다.
DDL 수행시 가능하면 온라인(Online) 옵션을 사용한다. 오라클 버전 업이 될 수록 온라인으로 수행 가능한 DDL은 점점 증가하는 추세다. 대부분 일반적인 DDL에서 온라인 옵션을 사용하는 것이 가능하다. 가령, CREATE INDEX 명령을 온라인 옵션으로 수행할 경우 테이블에 대해 SHARED 모드가 아닌 Sub-Shared(SS)모드로 TM 락을 획득한다. Sub-Shared 모드는 Sub-Exclusive 모드와 호환성이 있기 때문에 인덱스 생성하는 도중에 DML을 수행하는 것이 가능하다.
PARALLEL DDL을 사용해 DDL의 수행속도를 극대화 한다. 대용량 데이터에 대한 DDL 수행 시 PARALLEL 옵션을 적절히 사용하면 DDL 자체의 성능을 극대화할 수 있다. 더불어 Nologging 옵션을 함께 사용해도 좋다. DDL 수행 속도가 향상되면, 그와 비례해서 TX 락 경합에 의한 대기시간도 줄어든다.
Lock Table.. 을 이용해 의도적으로 TM 락을 획득하는 경우
Lock table ... 문을 이용해 의도적으로 TM 락을 획득 하는 경우네 TM 락 경합 발생 가능
동기화를 위해서 테이블 전체에 락을 거는 것보다는 DBMS_LOCK 패키지를 사용하거나 SELECT ... FOR UPDATE 등을 사용해서 락의 범위를 줄이는 방법을 고려해야 한다.
Direct/Parallel Load 작업을 수행한 경우
INSERT /*+ APPEND */ INTO .. 나 SQL*LOADER 의 DIRECT PATH LOAD 와 같은 일부 기능들은 해당 테이블에 대해 TM 락을 EXCLUSIVE 하게 획득한다. Direct load 작업은 SGA를 경유하지 않고 데이터 파일에 직접 쓰기를 수행하므로 작업이 수행하는 동안 테이블에 어떠한 변화도 허용해서는 안 된다. TM 락을 EXCLUSIVE 하게 획득함으로써 테이블에 대한 어떠한 변경도 허용되지 않는다는 것을 보장 받아야만 작업이 가능하다.