TM Lock은 DML 테이블 Lock으로 테이블을 보호하는 Lock이다.
select * from emp;
이제부터 이 트랜잭션을 트랜잭션A라고 부를 것이다.
update emp
set sal = 1024
where empno = 1;
그러면 이렇게 정상적으로 업데이트 된다. 아직 commit은 하지 않은 상태다.
이때, 다른 곳(새 cmd창)에서 empno가 1인 emp의 sal을 4021로 업데이트하고자 한다. 이 트랜잭션은 트랜잭션B라고 할 것이다.
update emp
set sal = 1024
where empno = 1;
이 쿼리를 날리면 날라가지 않고 그대로 멈춰있다. 트랜잭션A에서 이 행에 대해 Lock을 걸고 아직 commit을 하지 않았기 때문이다.
또 다른 cmd창을 열어 empno가 1인 emp의 sal을 0으로 업데이트 해볼 것이다. 이 트랜잭션은 트랜잭션C라고 할 것이다.
update emp
set sal = 0
where empno = 1;
이 쿼리 같은 이유로 역시 날라가지 않은 상태로 멈춰있게 된다.
현재 어떤 상황인지 확인할 때는 아래와 같은 쿼리를 날려주면 된다.
SELECT DISTINCT T1.SESSION_ID
, T2.SERIAL#
, T4.OBJECT_NAME
, T2.MACHINE
, T2.TERMINAL
, T2.PROGRAM
, T3.ADDRESS
, T3.PIECE
, T3.SQL_TEXT
FROM V$LOCKED_OBJECT T1
, V$SESSION T2
, V$SQLTEXT T3
, DBA_OBJECTS T4
WHERE 1=1
AND T1.SESSION_ID = T2.SID
AND T1.OBJECT_ID = T4.OBJECT_ID
AND T2.SQL_ADDRESS = T3.ADDRESS
ORDER BY T3.ADDRESS, T3.PIECE;
결과는 다음과 같다.
맨 아래 두 줄의 SQL_TEXT를 보면 트랜잭션A에 의해 Lock이 발생하여 수행되지 않은 UPDATE 쿼리를 확인할 수 있다.
지금과 같은 상황은 트랜잭션A가 commit하지 않았기 때문에 발생하는 현상이다. 이제 트랜잭션A에서 commit을 날려볼 예정이다.
트랜잭션 A에서 commit을 날렸을 때,
트랜잭션B에서 UPDATE 쿼리가 날라가게 된다. 트랜잭션C는 그대로다. 트랜잭션B가 먼저 수행되었기 때문에 위와 같은 결과가 나타난 것이다.