교착상태(Dead lock)에 대해서 아는 대로 설명해보세요.
교착 상태(deadlock)
교착 상태란 두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다. 예를 들어 하나의 사다리가 있고, 두 명의 사람이 각각 사다리의 위쪽과 아래쪽에 있다고 가정한다.
이때 아래에 있는 사람은 위로 올라가려고 하고, 위에 있는 사람은 아래로 내려오려고 한다면, 두 사람은 서로 상대방이 사다리에서 비켜줄 때까지 하염없이 기다리고 있을 것이고 결과적으로 아무도 사다리를 내려오거나 올라가지 못하게 되듯이, 전산학에서 교착 상태란 다중 프로그래밍 환경에서 흔히 발생할 수 있는 문제이다. 이 문제를 해결하는 일반적인 방법은 아직 없는 상태이다.
교착 상태의 조건
1971년에 E. G. 코프만 교수는 교착상태가 일어나려면 다음과 같은 네 가지 필요 조건을 충족시켜야 함을 보였다.
① 상호배제(Mutual exclusion) : 프로세스들이 필요로 하는 자원에 대해 배타적인 통제권을 요구한다. ② 점유대기(Hold and wait) : 프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다린다. ③ 비선점(No preemption) : 프로세스가 어떤 자원의 사용을 끝낼 때까지 그 자원을 뺏을 수 없다. ④ 순환대기(Circular wait) : 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가지고 있다. |
이 조건 중에서 한 가지라도 만족하지 않으면 교착 상태는 발생하지 않는다. 이중 순환대기 조건은 점유대기 조건과 비선점 조건을 만족해야 성립하는 조건이므로, 위 4가지 조건은 서로 완전히 독립적인 것은 아니다.
- 교착 상태의 종류
1) 순환 교착 (Cycle Deadlock)
교착상태를 설명할 때 보통 예로 드는 것이 "Cycle Dead Lock"이다. 두 세션이 필요한 리소스를 얻기 위해 서로 상대방이 Lock을 풀기를 기다리는 상태라고 설명할 수 있다. 예를 들면 아래와 같다.
위와 같이 실행시키면 한쪽 세션에서는 다음과 같은 결과를 볼 수 있다.
(1개 행 적용됨) 서버: 메시지 1205, 수준 13, 상태 50, 줄 1 트랜잭션(프로세스 ID 54)이 lock 리소스에서 다른 프로세스와의 교착 상태가 발생하여 실행이 중지되었습니다. 트랜잭션을 다시 실행하십시오. |
▲교착상태란 무엇인가를 직관적으로 알려주는 예시
2) 변환 교착 (Conversion DeadLock)
Conversion DeadLock 은 잠금모드가 SharedLock에서 UPD-Lock 혹은 X-Lock으로 전환될 때 발생하는 문제로서, 채번(일련번호 매기는 일)과 관련해서 발생하는 경우가 많다.
① 세션 A가 트랜젝션을 건 후 어떤 Row에 공유잠금(S-Lock)을 걸었다고 가정해보자 ② 세션 B도 트랜젝션을 건 후 그 Row에 공유잠금을 걸었다. 공유잠금끼리는 서로 호환이 되므로 당연히 가능하다. ③ 이 상태에서 세션 A는 그 Row에 Update를 시도한다. 이 Row에는 세션 B에서 공유잠금을 걸었으므로 세션 A는 배타적 잠금을 을 걸기 위해 세션 B가 공유잠금을 풀어주기를 기다린다. ④ 이때, 세션 B도 그 Row에 Update를 시도한다 |
과연 어떻게 될까? A는 B의 공유잠금 때문에 Update를 진행하지 못하고, B는 A의 공유잠금 때문에 Update를 진행하지 못하게 된다. 이것이 Conversion DeadLock이다. 실제 테스트를 해보면 다음과 같다.
테스트해보면 데드락이 발생하는 것을 확인할 수 있다. 위와 같은 SQL이 데드락이 발생하지 않도록 하려면 어떻게 해야 할까? 의 교착상태는 SELECT시 공유잠금이 동시에 걸렸기 때문에 발생한 것이므로, ELECT시에 다음과 같이 잠금 힌트를 주어 처음부터 명시적으로 UPDLOCK을 걸어주면 교착상태를 방지할 수 있다.
SELECT @NUM = VAL + 1 FROM TAB1 WITH (UPDLOCK) WHERE NUMTYPE = 'TestApp’
|
교착상태를 줄이는 5가지 방법
DeadLock을 줄이기 위해서는 다음과 같은 방법들이 있다.
① 인덱스를 설정한다. 인덱스가 없으면 Lock이 걸리는 범위가 훨씬 넓어지기 때문에 교착상태가 발생하기 쉬워진다.
② 자원들을 한쪽으로 사용한다. A와 B라는 테이블이 있다면 모든 세션에서 A->B 순서로 사용하도록 한다.
③ 트랜잭션은 가급적이면 짧게 만든다.
④ 테이블의 크기를 작게 쪼갠다. (정규화)
⑤ Transaction Isolation Level을 "Read Uncommitted"로 설정한다.
커뮤니티 Q&A
위 이론과 관련된 게시글이에요.
이해가 안 되거나 궁금한 점이 있다면 커뮤니티에 질문해 보세요!
게시글 작성하기