데이터베이스 - 교착상태(Deadlock)
What is Deadlock?
교착상태(Deadlock)이란?
데이터베이스에서는 기본적으로 트랜잭션들의 동시성을 제어하기 위해 잠금(Locking)을 사용한다. 이러한 잠금은 데이터의 무결성을 지켜주지만 그 부작용으로 교착상태가 발생할 수 있다. 교착상태란 여러개의 트랜잭션들이 실행을 하지 못하고 서로 무한정 기다리는 상태를 의미한다.
트랜잭션 1이 테이블 B의 첫번째 행의 잠금을 얻고 트랜잭션 2도 테이블 A의 첫번째 행의 잠금을 얻고나서
Transaction 1> create table B (i1 int not null primary key) engine = innodb;
Transaction 2> create table A (i1 int not null primary key) engine = innodb;
Transaction 1> start transaction; insert into B values(1);
Transaction 2> start transaction; insert into A values(1);
트랜잭션을 commit 하지 않고 서로의 첫번째 행에 잠금을 요청하면 Deadlock 발생
Transaction 1> insert into A values(1);
Transaction 2> insert into B values(1);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
교착 상태 해결방법
예방 기법
각 트랜잭션이 실행되기전에 필요한 데이터를 모두 잠금(Locking)하는 것. 하지만 데이터가 많이 필요할 경우 모든 데이터를 잠금해야 되기 때문에 트랜잭션의 병행성을 보장하지 못한다. 뿐만 아니라 몇몇 트랜잭션들은 계속해서 처리를 못하게 되는 기아 상태가 발생할 수 있다.
회피 기법
위의 단점 때문에 실제로 교착상태를 해결하기 위한 방법으로 회피 기법이 많이 사용된다. 회피 기법은 자원을 할당할 때 시간 스탬프(Time Stamp)를 사용하여 교착상태가 일어나지 않도록 회피하는 방법으로 Wait-Die 방식과 Wound-Wait 방식이 있다.
Wait-Die 방식
다른 트랜잭션이 데이터를 점유하고 있을 때 기다리거나(Wait) 포기(Die)하는 방식으로 선행 트랜잭션이 접근하면 대기(wait), 후행 트랜잭션이 접근하면 포기(die)한다. 즉, 오래된 프로세스에게 대기의 기회를 제공하고, 최신 프로세스는 자주 복귀함으로써 오버헤드의 가능성이 있다.
Wound-Wait 방식
다른 트랜잭션이 데이터를 점유하고 있을 때 빼앗거나(Wound) 기다리는(Wait) 방식으로 선행 트랜잭션이 접근하면 선점(wound), 후행 트랜잭션이 접근하면 대기(wait)한다. 즉, 오래된 프로세스에게 선점의 기회를 제공하고 최신 프로세스는 대기함에 따라 복귀를 최소화한다.
낙관적 병행 기법
낙관적 병행 기법은 트랜잭션이 실행되는 동안에는 아무런 검사를 하지 않고, 트랜잭션이 다 실행된 이후에 검사 후 문제가 있다면 되돌리는 방법
빈도 낮추기
교착 상태의 빈도를 낮추는 방법으로는
- 트랜잭션을 자주 커밋
- 트랜잭션들이 동일한 테이블 순으로 접근하게 한다.
- 읽기 잠금 획득( SELECT ~ FOR UPDATE)의 사용을 피한다.
- 테이블 단위의 잠금을 획득해 갱신을 직렬화
참고: 회피 기법
*틀린 부분이 있으면 언제든지 말씀해 주시면 공부해서 수정하겠습니다.