-
DB - 블로킹(Blocking)과 데드 락(Deadlock)DB 2024. 11. 11. 22:27
블로킹(Blocking)
정의:
- 한 트랜잭션이 자원(테이블, 행 등)을 Lock 하고 있을 때, 다른 트랜잭션이 해당 자원에 접근하지 못하고 기다리는 현상
특징:
- 일시적인 현상으로, Lock 이 해제되면 자연스럽게 해결됨
- 정상적인 데이터베이스 동작의 일부
- 데이터 일관성을 보장하기 위한 매커니즘
예시 코드)
-- 블로킹 예시 -- 트랜잭션 1 BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 여기서 잠시 멈춤 (아직 COMMIT하지 않음) -- 트랜잭션 2 (동시 실행) BEGIN; UPDATE accounts SET balance = balance + 50 WHERE id = 1; -- 트랜잭션 1이 COMMIT할 때까지 대기 (블로킹)
데드 락(Deadlock)
정의:
- 두 개 이상의 트랜잭션이 각각의 자원을 점유한 상태에서 상대방의 자원을 요청하며 무한히 기다리는 상태
특징:
- 자연스럽게 해결되지 않음
- 시스템의 개입이 필요함
- 순환 대기가 발생
발생조건
- 상호 배제(Mutual Exclusion)
- 자원은 한 번에 하나의 트랜잭션만 사용 가능
- 다른 트랜잭션은 해당 자원 사용 불가
- 점유와 대기(Hold and Wait)
- 트랜잭션이 최소한 하나의 자원을 보유
- 다른 트랜잭션이 사용 중인 자원을 추가로 요청
- 비선점(No Preemption)
- 이미 할당된 자원을 강제로 빼앗을 수 없음
- 자원을 가진 트랜잭션이 자발적으로 해제하기 전까지 계속 사용
- 순환 대기(Circular Wait)
- 트랜잭션들이 순환 형태로 자원을 요청
- 각 트랜잭션은 다음 트랜잭션이 가진 자원을 요청
예시 코드)
-- 데드락 예시 -- 트랜잭션 1 BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 여기서 id=2인 레코드의 락을 기다림 UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 트랜잭션 2 (동시 실행) BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 2; -- 여기서 id=1인 레코드의 락을 기다림 UPDATE accounts SET balance = balance + 100 WHERE id = 1;
데드락 해결 방안
1. 예방(Prevention)
-- 1. 순서 기반 접근 BEGIN; SELECT * FROM accounts WHERE id IN (1, 2) ORDER BY id FOR UPDATE; -- 항상 작은 ID부터 잠금 -- 2. 한 번에 모든 자원 획득 BEGIN; SELECT * FROM accounts WHERE id IN (1, 2, 3) FOR UPDATE;
2. 회피(Avoidance)-- 타임아웃 설정 SET innodb_lock_wait_timeout = 50; -- 50초 후 타임아웃 -- 트랜잭션 격리 수준 조정 SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
3. 감지 및 복구(Detection & Recovery)
-- 데드락 정보 확인 SHOW ENGINE INNODB STATUS; -- 데드락 발생 시 자동으로 롤백되는 트랜잭션 처리 BEGIN; DECLARE EXIT HANDLER FOR DEADLOCK BEGIN ROLLBACK; -- 재시도 로직 END;
데드락 방지를 위한 Best Practices
- 애플리케이션 레벨
- 트랜잭션 범위를 최소화
- 일관된 순서로 데이터 접근
- 대량 처리 시 배치 처리 활용
- 적절한 인덱스 설계
- 데이터베이스 레벨
- 적절한 격리 수준 설정
- 인덱스 최적화
- 주기적인 모니터링
- 타임아웃 설정
- 운영관리
- 데드락 로그 모니터링
- 성능 지표 관리
- 주기적인 테이블 유지보수
결론
블로킹과 데드락은 모두 동시성 제어 과정에서 발생하는 현상이지만, 블로킹은 정상적인 동작의 일부로 볼 수 있는 반면, 데드락은 비정상적인 상황으로 보고 적극적인 방지가 필요하다. 효과적인 데이터베이스 설계와 모니터링을 통해 두 현상 모두 최소화할 수 있다.
특히 실제 운영환경에서는 데드락 발생 시 자동으로 재시도하는 로직을 구현하는 것이 중요하다.
서버측에서 재시도 관련 처리를 테스트를 진행한 코드를 다음 링크에서 확인 가능
https://github.com/O-Seonsik/lock-test/tree/master/src/modules/products
'DB' 카테고리의 다른 글
낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock) (0) 2024.11.14 공유 락(Shared Lock, S-Lock)과 배타 락(Exclusive Lock, X-Lock) (3) 2024.11.10 Isolation level - 트랜잭션 격리 수준 (0) 2024.09.22