반응형
트랜잭션(Transaction) 환경에서 데이터 정합성을 유지하고자 할 때, 꼭 알아야 하는 기능이 있습니다. 바로 SELECT FOR UPDATE입니다.
이 구문은 동시에 여러 사용자가 같은 데이터를 조작할 수 없도록 레코드에 잠금(Lock)을 거는 기능으로, MySQL InnoDB 엔진을 사용할 때 매우 중요하게 작동합니다.
✅ SELECT FOR UPDATE란?
SELECT FOR UPDATE는 트랜잭션 내에서만 사용 가능한 SELECT 문으로, 조회된 행(row)에 대해 쓰기 잠금(Write Lock)을 겁니다.
다른 세션은 해당 행을 수정하거나 삭제할 수 없고, 잠금이 풀릴 때까지 대기하게 됩니다.
기본 문법
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 이후 UPDATE or DELETE 실행 가능
COMMIT;
반응형
✅ 왜 필요한가? – 데이터 정합성 보장
동시에 여러 유저가 하나의 데이터를 조작할 때, 잘못하면 다음과 같은 문제가 생길 수 있습니다:
- 중복 처리
- 경합 조건(Race Condition)
- 정합성 깨짐
SELECT FOR UPDATE를 사용하면 트랜잭션이 끝나기 전까지 행을 보호하여 위와 같은 문제를 방지할 수 있습니다.
✅ 실전 예제 1: 은행 이체 처리
START TRANSACTION;
-- 송신자 계좌 잠금
SELECT balance FROM accounts WHERE user_id = 1 FOR UPDATE;
-- 수신자 계좌 잠금
SELECT balance FROM accounts WHERE user_id = 2 FOR UPDATE;
-- 금액 차감 및 이체
UPDATE accounts SET balance = balance - 10000 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 10000 WHERE user_id = 2;
COMMIT;
🔍 설명: 두 계좌의 금액을 안전하게 처리하기 위해 SELECT FOR UPDATE로 먼저 락을 걸고, 이후 UPDATE 실행 → COMMIT으로 적용
✅ 실전 예제 2: 재고 감소 처리 (쇼핑몰)
START TRANSACTION;
SELECT stock
FROM products
WHERE product_id = 1001
FOR UPDATE;
UPDATE products
SET stock = stock - 1
WHERE product_id = 1001;
COMMIT;
🔍 설명: 동시에 수많은 사용자가 구매 요청을 보낼 때 재고가 음수가 되는 것을 방지할 수 있음
반응형
✅ SELECT FOR UPDATE 주의사항
항목 | 설명 |
🔒 사용 가능한 스토리지 엔진 | InnoDB (MyISAM은 미지원) |
🔄 반드시 트랜잭션 내에서 사용 | START TRANSACTION 없이 실행 시 무효 |
🔍 WHERE 조건 필수 | 불필요한 테이블 전체 락 방지 |
⚠️ 인덱스 없는 컬럼은 범위 잠금이 불안정 | 가능하면 인덱스를 활용하자 |
❗ 잠금이 해제되는 시점은 언제?
- COMMIT 또는 ROLLBACK 시점에 잠금이 해제됩니다.
✅ SELECT FOR UPDATE vs LOCK IN SHARE MODE
항목 | SELECT FOR UPDATE | LOCK IN SHARE MODE |
잠금 유형 | 쓰기 잠금 (X Lock) | 공유 잠금 (S Lock) |
다른 세션의 읽기 허용 | ❌ 불가능 (잠금 대기) | ✅ 가능 |
쓰기 가능 여부 | ✅ 가능 | ❌ 불가능 |
사용 목적 | 수정/삭제 목적의 조회 | 단순 조회, 정합성 보장 목적 |
✅ 성능과 동시성 팁
- 짧은 트랜잭션이 핵심입니다. 트랜잭션이 길어지면 대기하는 세션이 많아져 전체 성능이 저하됩니다.
- WHERE 절로 명확한 조건 지정 → 불필요한 레코드에 락을 걸지 않도록
- 트랜잭션 중에는 가능한 최소한의 쿼리만 수행하세요.
✅ 공식 가이드 문서 참고
- MySQL SELECT FOR UPDATE:
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html - InnoDB 트랜잭션 및 잠금 처리:
https://dev.mysql.com/doc/refman/8.0/en/innodb-transactions.html
반응형
'DB' 카테고리의 다른 글
[MySQL] ENUM 성능 최적화와 실무 활용 팁 총정리 (0) | 2025.06.30 |
---|---|
[MySQL] SELECT와 ENUM 컬럼을 활용한 데이터 정합성 및 조회 최적화 전략 (1) | 2025.06.30 |
[MySQL] SELECT 쿼리를 VIEW로 추상화 (복잡한 SQL을 깔끔하게 관리) (1) | 2025.06.30 |
[MySQL] LOCK IN SHARE MODE 완전 정복 – 공유잠금, 읽기전용 (0) | 2025.06.30 |
[MySQL] JSON 컬럼 SELECT 조회 완벽 가이드 (0) | 2025.06.26 |
[MySQL] LIKE와 REGEXP 차이부터 고급 패턴 검색까지 완벽 정리 (0) | 2025.06.26 |
[MySQL] IS NULL과 IS NOT NULL 완전 정복! 조건절로 놓치지 말아야 할 핵심 포인트 (2) | 2025.06.26 |
[MySQL] SELECT 문에서 EXISTS와 IN 조건절 (1) | 2025.06.26 |