데드락이란?
- 둘 이상의 트랜잭션이 교착상태에 있는 것으로 서로 맞서서 서로가 먼저 물러서기를 기다리며 대치하고 있는 상태를 말한다.
- 예를 들어, 테이블A와 테이블B가 있는데, 트랜잭션1이 A테이블의 일부 행을 락을 걸고 B테이블의 특정 행을 업데이트 하러 갔다. 근데 트랜잭션2가 B테이블의 그 행을 락을 걸고 A테이블로 가서 업데이트를 하려는데 락이 걸려있다. 이런 상태가 교착상태이다.
교착상태라는 것을 어떻게 감지할까?
- 타임아웃
- 일정시간 동안 트랜잭션이 실행되지 않는다면, 교착상태임을 감지하고 롤백 시킨다.
- 사이클 탐색
- 사이클이 형성되었다는 것을 알게 되면 교착상태임을 알 수 있다.
⇒ 그러나 DB가 크다면 일일이 교착상태를 감지하기에는 비용이 너무 크다. 그래서 교착상태를 미리 방지하고자 한다.
교착상태를 어떻게 방지할까?
-
격리 수준을 변경시킨다.
- SERIALIZABLE 이면 격리성이 가장 높아지므로 동시에 트랜잭션이 일어날 일이 없다.
- 즉 격리성을 높이면 된다.
- 하지만 SERIALIZABLE이 아닌 이상 교착상태를 100% 방지할 수는 없다.
-
서비스의 로직을 수정
- 교착이 되지 않도록 트랜잭션의 방향을 일관되게 바꾼다.
-
wait-die 또는 wound-wait
타임스탬프(먼저 태어난 트랜잭션) 기반으로 트랜잭션을 대기시키거나, 선점하게 하거나, 종료하게 한다.
- wait-die (비선점)
- T10, T20, T30 트랜잭션이 있다고 치자.
- 먼저 태어난 T10이 T20에게 데이터를 달라고 한다. → T10이 선점을 할 순 없지만 기다릴 수 있다. wait
- 나중에 태어난 T30이 T20에게 데이터를 달라고 한다. → 죽는다;; die
- wound-wait (선점)
- 위의 예시처럼 트랜잭션이 있다.
- 먼저 태어난 T10이 T20에게 데이터를 달라고 한다. → T10이 T20에게서 순서를 뺏는다. T20은 상처입는다. wound
- T30이 T20에게 데이터를 달라고 한다. → T30은 기다린다. wait