728x90
동시성 제어 방식: 비관적 락 vs 낙관적 락
🔒 비관적 락 (Pessimistic Lock)
동시성 제어를 위한 가장 보편적인 방법
락을 통한 줄세우기
✅ 장점
- 동시성 이슈를 DB에서 강제로 막기 때문에 안전함
❌ 단점
- 락을 통한 동시성 제어는 불필요한 대기 상태를 만듦
- 동시성이 빈번하지 않은 쿼리에도 락이 걸려 다른 쿼리가 대기 상태가 됨
- 락 범위가 커질수록 성능 저하 발생 (Connection Pool 고갈 가능성)
💡 MySQL에서의 쓰기락 (Exclusive Lock) 예시
START TRANSACTION;
-- 특정 조건의 Row에 쓰기락을 건다
SELECT *
FROM post
WHERE member_id = 2
AND contents = 'v'
FOR UPDATE;
-- 작업이 끝난 후 커밋
COMMIT;
FOR UPDATE
는 쓰기락을 의미하며, 락은COMMIT
시점에 해제됨performance_schema.data_locks
를 통해 락 상태 확인 가능
🪄 낙관적 락 (Optimistic Lock)
동시성 이슈가 자주 발생하지 않길 기대하고, 애플리케이션 단에서 제어
데이터 충돌이 발생할 수 있으므로, 실패에 대한 처리를 명시적으로 구현해야 함
✅ 장점
- 락을 걸지 않기 때문에 성능이 좋음
- 동시성이 낮은 환경에 적합
❌ 단점
- 충돌 발생 시 재시도 로직 또는 예외 처리를 개발자가 직접 구현해야 함
🔁 핵심 개념: CAS (Compare And Set)
조건: 특정 버전에서만 갱신 허용 → 충돌 방지
🧪 예제: 낙관적 락 시나리오
이름 | 잔액 | 버전 |
---|---|---|
홍길동 | 1000원 | 1 |
- 트랜잭션_1:
SELECT * FROM account WHERE name = '홍길동'
→ (잔액: 1000, 버전: 1) - 트랜잭션_2:
SELECT * FROM account WHERE name = '홍길동'
→ (잔액: 1000, 버전: 1) - 트랜잭션_1:
UPDATE account SET 잔액 = 900, 버전 = 2 WHERE name = '홍길동' AND 버전 = 1
→ ✅ 성공 - 트랜잭션_2:
UPDATE account SET 잔액 = 900, 버전 = 2 WHERE name = '홍길동' AND 버전 = 1
→ ❌ 실패 (버전 불일치)
💡 처리 방식 예
- 재시도 로직
- 사용자에게 알림
- 충돌 무시
✅ 정리 비교
항목 | 비관적 락 | 낙관적 락 |
---|---|---|
방식 | DB 락 이용 (FOR UPDATE 등) | 애플리케이션 단에서 버전 비교 |
성능 | 낮음 (동시성 많을수록 대기 발생) | 높음 (락 없음, 대신 실패 대비 필요) |
동시성 강도 | 높음 (DB가 직접 충돌 방지) | 낮음 (충돌 발생 가능성 존재) |
충돌 처리 | 자동 (DB가 막음) | 수동 (코드에서 재시도 등 구현 필요) |
728x90
'Server' 카테고리의 다른 글
Session 이란? (0) | 2024.02.24 |
---|---|
동시성 제어 (0) | 2024.02.18 |
[비관적인락/PESSIMISTIC]_쓰기락 테스트 (0) | 2024.02.06 |
[비관적인락/PESSIMISTIC]_쓰기락과 읽기락 (0) | 2024.02.06 |
[디자인 패턴] 추상 팩토리 패턴 (0) | 2024.02.03 |