083 락(LOCK) 이해하기
LOCK
: 세션(유저)이 특정 데이터를 수정하게 되면 COMMIT하기 전까지 수정한 행(row)에 락을 검.
특정 세션이 변경한 데이터를 다른 세션이 변경하지 못하도록 막는 기능
-> 만약 lock이 없다면 데이터의 일관성이 깨짐
예시) 위에서 아래로 시간 순서상 진행된다고 이해해보기
c##scott | c##scott |
A session | B session |
UPDATE emp SET sal = 9000 WHERE ename = 'KING'; |
|
UPDATE emp SET sal = 0 WHERE ename = 'KING'; COMMIT; |
|
SELECT ename, sal FROM emp; |
세션 A에서 마지막 쿼리문 수행할 때 0으로 나온다면? 데이터의 일관성이 깨져버림.
∴ 해당 행에다 락(lock)을 걸어, 다른 행들이 수정하지 못하게 막음.
실습
명령 프롬프트 창 2개 켜고 실습
1. 둘다 접속
sqlplus c##scott/tiger
2. user 확인
show user;
3. Session A창에 KING의 월급 업데이트
UPDATE emp
SET sal = 9000
WHERE ename = 'KING';
4. Session B창에 KING의 월급 업데이트 시도
아무 변동 없이 커서만 깜빡이고 있음. ( KING의 행에 락이 걸려있기 때문)
5. Session A창 커밋이나 롤백하기
세션 A에서 커밋되는 순간 세션 B의 락이 풀리면서 업데이트 진행됨.
6. Session A에서 한번 더 업데이트
( B롤백해놓고 시작하기)
7. Session B에서 한번 더 업데이트 시도
다른 컬럼을 대상으로 업데이트 함에도 락이 걸려서 아무 반응 없이 대기 중
왜냐하면 락은 행단위로 걸리기 때문!!
* 업데이트 하는 컬럼이 달라도, 행이 같으면 커밋이나 롤백 전까지 락 걸려서 대기해야 함.
Lock holder와 waiter 찾는 쿼리문
select decode(status,'INACTIVE',username || ' ' || sid || ',' || serial#,'lock') as Holder,
decode(status,'ACTIVE', username || ' ' || sid || ',' || serial#,'lock') as waiter, sid, serial#, status
from( select level as le, NVL(s.username,'(oracle)') AS username,
s.osuser,
s.sid,
s.serial#,
s.lockwait,
s.module,
s.machine,
s.status,
s.program,
to_char(s.logon_TIME, 'DD-MON-YYYY HH24:MI:SS') as logon_time
from v$session s
where level>1
or EXISTS( select 1
from v$session
where blocking_session = s.sid)
CONNECT by PRIOR s.sid = s.blocking_session
START WITH s.blocking_session is null);
LOCK HOLDER, WAITER에 대한 정보 확인 가능 (SID, SERIAL#)
락 홀더의 세션을 KILL하시오.
ALTER SYSTEM KILL SESSION '857,63293';
kill되면서 락때문에 대기하고 있던 세션B(오른쪽 이미지)의 update 수행됨.
동시에 세션A(락 홀더)가 조회를 해보면 세션이 종료됐다는 알림과 함께 롤백됨.
테이블의 데이터를 update하면 lock이 행 단위로 걸림.
db에 데이터 수정 작업을 했으면 꼭 commit을 해서 마무리 해야함.
안 그러면 다른 세션들이 lock에 걸리게 됨.
문제 479. 아래와 같이 c##scott세션을 2개 열고 update를 수행하시오.
c##scott | c##scott |
A session | B session |
UPDATE emp SET sal = 9000 WHERE job = 'SALESMAN'; |
|
UPDATE emp SET sal = 7000 WHERE ename = 'MARTIN';OMMIT; |
B 세션 대기중
이유: A 세션에서 업데이트한 4개의 행에 lock이 걸려있는데 MARTIN도 그 중 하나이기 때문.
(MARTIN이 SALESMAN이기도 함.)
문제 480. 이번에는 holder를 죽이지 말고, waiter를 kill 하시오.
ALTER SYSTEM KILL SESSION '981,41115';
문제 481. emp 테이블 전체에 LOCK을 겁니다.
LOCK TABLE emp IN EXCLUSIVE MODE;
session A에서 테이블 전체에 대해 잠금을 걸었기 때문에, session B에서는 emp 테이블에 대한 어떤 update를 시도해도 실행X
session A에서 롤백하는 순간 락이 풀리면서, session B 업데이트 수행
문제 482. c##scott 유저로 3개의 세션을 열고, 다음과 같이 업데이트하시오.
c##scott | c##scott | c##scott |
A session | B session | C session |
update emp set sal = 8700 where ename = 'ALLEN'; |
||
update emp set sal = 0 where ename = 'ALLEN'; |
||
update emp set deptno = 70 where ename = 'ALLEN'; |
A는 업데이트 중
QUEUE : B,C 순으로 대기 중
A COMMIT
B deQueue : 큐에서 빠져나가면서 업데이트 (선입선출이라 먼저 업데이트하면서 큐에서 나감)
C inQueue : 아직 큐에서 대기 중