본문 바로가기
ORACLE/DB

[Oracle] Transaction Dead Lock 발생 실습, 이론 말고 직접 만들어 보자 :: 마이자몽

by 마이자몽 🌻♚ 2020. 3. 26.

Transaction Dead Lock 교착상태

잘못된 자원 관리로 인하여 둘 이상의 프로세스가 함께 멈추어 버리는 현상..........

도저히 무슨 말인지 모르겠습니다. 간단하게 설명하자면, Transaction이 서로 꼬여서 작업이 멈춰버리는 것 입니다. Dead Lock 교착상태에 대한 정보를 검색해보면 위와 비슷한 내용의 정의를 내립니다. 또 교착상태로 빠질 수 있는 4가지조건이라고 해서 상호 배제(Mutual Exclusion), 점유와 대기 Hold and Wait, 비선점(No Preemption), 환형대기(Circular Wait) 이런 이론적인 내용 밖에 안나옵니다. 중요한 내용이고 꼭 알아야하는 내용은 맞지만... 글로만 봐서 대충 무슨 느낌인지는 알겠는데, 정확히 모르겠고... 이해가 안되는 분들이 많으실거라 생각합니다.

 

이번 글에서는 Dead Lock을 실제로 발생시켜 Dead Lock에 대한 확실한 이해를 할 수 있도록 도와드리겠습니다.

 

 

Transaction Update

실습을 진행하기 전에 Transaction에서 Update작업을 할때 처리과정이 어떻게 되는지 꼭 알고 넘어가야합니다.

1
2
3
UPDATE EMPLOYEES
SET SALARY = 3000
WHERE EMPLOYEE_ID = 201;

위의 쿼리를 실행했을 때 어떤 일이 벌어질까요?

1. 행 레벨 LOCK

2. UNDO SEGMENT BUFFER 확보 및 정보 기록

3. 데이터 UPDATE

4. COMMIT & 행 UNLOCK

 

Transaction에서 Update를 할 경우 읽기 일관성을 유지하기 위해 행레벨에서 LOCK을 걸어버립니다. 다른 Transaction에서 Update 작업을 할 수 없도록 막는 작업입니다. 그 후 다른 Transaction에서 SELECT를 할 경우 아직 COMMIT을 하지 않았기 때문에 이전 정보를 UNDO BLOCK에서 조회할 수 있도록 정보를 기록해주고 데이터 UPDATE 작업을 진행합니다. Transaction이 최종적으로 끝나면 행레벨 락을 풀어 줍니다. UPDATE 작업의 처리과정은 간략하게 위와같이 진행됩니다. 그럼 이런 UPDATE하는 과정에서 어떻게 DEAD LOCK 교착상태가 발생하는 것일까요?

 

 

Dead Lock 발생 시키기

SQL PLUS를 이용해서 HR 계정에 20번 부서에서 근무하고 있는 사원들을 검색해봤습니다. 201, 202번 사원 2명이 근무하고 있습니다. 그럼 이번에는 데이터를 변경해보겠습니다.

 

 

이상 없이 급여가 13000에서 3000으로 변경된 것을 확인했습니다.

 

 

이번에는 Transaction의 교착 상태를 발생시키기 위해 콘솔창을 하나 더 이용해서 다른 TransactionB로 20번 부서의 사원 정보를 확인해봤습니다. 아직 COMMIT을 진행하지 않아서 UNDO SEGMENT에서 이전 정보의 데이터를  보여줍니다. 현재 201번 사원은 행레벨 LOCK이 걸려 있는 상태입니다.

 

 

UPDATE 쿼리를 실행했으나... 결과가 나오지 않고 기다리고 있습니다. 201번 사원에 대한 정보는 첫번째 Transaction A에서 UPDATE를 했습니다 . 두번째 Transaction B에서 같은 행을 UPDATE하려고 하면 WAITING을 하게 됩니다. Transaction이 끝나기를 기다리고 행의 LOCK이 풀리게 되면 WAITING이 끝나고 UPDATE 작업을 진행합니다.

 

 

TRANSACTION A에서 COMMIT 명령을 입력하자마자 WAITING은 풀리고 TRANSACTION B에서 UPDATE 작업을 했습니다. SELECT를 통해 결과를 확인해보니  TRANSACTION B에서 변경한 4000으로 수정되었습니다. 그럼 TRANSACTION A에서 이제 SELECT로 20번 부서 사원들의 정보를 확인해보면 201번 사원의 급여는 어떻게 되어 있을까요??

 

아직 TRANSACTION B에서 COMMIT을 하지 않았기 때문에 마지막으로 COMMIT이 된 3000으로 보여질 겁니다. 이제는 201번 행에 대한 LOCK은 TRANSACTION B가 소유하고 있습니다.

 

WAITING을 발생시키는 실습까지 해봤습니다. 이제 DEAD LOCK을 어떻게 발생시킬지 감이 조금 오시나요?

 

 

이제는 진짜  DEAD LOCK을 발생시키기 위해 다시 TRANSACTION A로 넘어왔습니다. 이번에는 201번 사원이 아닌 202번사원의 데이터를 UPDATE 했습니다.

 

이제는 두개의 행 모두가 LOCK이 걸린 상태입니다. 201번 사원의 행은 TRANSACTION B가, 202번 사원의 행은 TRANSACTION A가 LOCK을 하고 있는 상태입니다. 두 TRANSCTION 모두 끝나지 않았고... 이상태에서 TRANSACTION A가 201번 사원을 UPDATE 시도하고 TRANSACTION B가 202번 사원을 UPDATE하려고하면 어떻게 될까요? 두개의 TRANSACTION 모두 WAITING에 들어가고 Dead Lock 교착상태에 빠지게 됩니다.

 

 

두개의 TRANSACTION 모두 WAITING에 들어가서 아무것도 못하는 상태가 됩니다. 이게 바로 Dead Lock 교착상태입니다. 그럼 이런 교착상태를 방지하기 위해서 어떻게 해야할까요?

 

 

Oracle의 경우, Dead Lock을 감지하면 한쪽  Transaction을 풀어버립니다. TRANSACTION A의 마지막 UPDATE 내용에 오류가 발생되고 COMMIT을 먼저 하도록 유도합니다. TRANSACTION B는 아직 WAITING 상태로 남아있고, TRANSACTION A의 COMMIT을 기다립니다.

 

 

진행한 예제의 데이터 흐름을 순차적으로 보면 위와 같습니다. Dead Lock 발생 이후 TRANSACTION A, B 순서대로 COMMIT을 하게 되면 결국 마지막에 UPDATE한  TRANSACTION의 결과로 COMMIT됩니다.

 

태그

댓글0