일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 아키텍쳐 개선
- 쿠키
- 디버깅
- 몽고 인덱스
- 구현
- langgraph
- BFS
- ai agent
- 누적합
- 관측가능성
- next-stock
- spring event
- 베타적락
- 결제서비스
- 완전탐색
- gRPC
- 이분탐색
- 프로그래머스
- JPA
- ipo 매매자동화
- docker
- 백준
- 크롤링
- 추천 검색 기능
- 셀러리
- piplining
- dau 3만명
- 카카오
- AWS
- 알람시스템
- Today
- Total
코딩관계론
DB Exclusive Lock 에러 본문
최근 업무 중 특정 기능 업데이트 이후 데이터베이스에서 예상치 못한 빈도의 Lock Raise 오류가 발생하였다. 장애 현상은 다음과 같은 트랜잭션 간 경쟁 상황에서 비롯되었다. 이러한 상황에서 발생하는 락과 이를 해결하기 위한 전략에 대해 정리하고자 한다.
장애 현상
- 트랜잭션 A가 특정 행(ROW1)에 대한 업데이트를 수행하며 배타적 락(Exclusive Lock)을 획득했다.
- 트랜잭션 A가 완료되지 않은 상태에서 트랜잭션 B가 같은 행(ROW1)에 대한 업데이트를 시도하면서 락 충돌(Lock conflict)이 발생하여 오류가 발생했다.
배타적 락(Exclusive Lock, X-Lock)
먼저 이 문제를 해결하기 위해선 배타적 락 대해서 알아야 한다. 배타적 락은 데이터 변경 작업을 수행할 때 발생하는 락으로, 주로 UPDATE, DELETE, 또는 SELECT FOR UPDATE 작업 시 획득된다. 배타적 락이 설정된 데이터는 다른 트랜잭션의 쓰기 작업을 차단하여 데이터의 일관성을 유지한다. 일반적인 읽기 작업(SELECT)은 허용되지만, 쓰기 작업을 위한 다른 배타적 락은 해당 락이 해제될 때까지 대기 상태로 전환된다.
배타적 락 실험 예시
다음의 실험을 통해 배타적 락의 동작 방식을 확인할 수 있다.
-- 테이블 생성
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
balance INT NOT NULL
);
-- 초기 데이터 삽입
INSERT INTO accounts (name, balance) VALUES ('Alice', 1000);
INSERT INTO accounts (name, balance) VALUES ('Bob', 1000);
이후 트랜잭션을 통해 아래 작업을 수행한다.
-- 트랜잭션 A
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
SELECT * FROM accounts WHERE id = 1;
이 상태에서 새로운 트랜잭션 B를 생성하여 같은 행을 업데이트하면 락 충돌이 발생한다.
-- 트랜잭션 B (새로운 연결)
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 1;
트랜잭션 A가 커밋 또는 롤백되지 않는 한 트랜잭션 B의 작업은 블로킹(blocking) 상태가 되어 기다리게 된다.
해결 전략
이러한 문제를 해결하기 위해 특정 컬럼에 대한 명시적인 UPDATE 문을 제거하고 모든 변경 작업을 ORM의 save 메서드를 통해 수행하도록 변경하였다. 동시에 낙관적 락을 도입하였다. 이렇게 하면 특정 컬럼에 대한 배타적 락을 명시적으로 걸 위험이 없어지고, 충돌 발생 시 버저닝(versioning)을 통해 충돌을 효율적으로 관리할 수 있게 된다.
출처
'개발' 카테고리의 다른 글
DAU 3만명 이 구조로는 못 버텨요… 내가 직접 설계한 비동기 설문 시스템 (1) | 2025.06.22 |
---|---|
일평균 700건 이상의 요청에서 "세션 점유 중" 오류를 10건 이하로 (0) | 2025.06.16 |
결제서비스 (0) | 2024.09.02 |
Redis 분산 시스템에서의 동시성 문제 해결 (0) | 2024.08.25 |
TPS 2에서 TPS 10,000까지의 험난한 과정 (0) | 2024.08.22 |