오늘의하루
[MySQL 8.0] 선착순 쿠폰 발급 로직 구현에 대한 고찰 본문
최근 MySQL을 공부하면서 선착순 쿠폰 발급을 효율적으로 처리하는 로직을 고민해보았습니다.
이 글에서는 MySQL 8.0의 고급 기능을 활용하여 동시성 제어와 쿠폰 발급 로직을 구현하는 방법을 정리해 보겠습니다.
MySQL 8.0 고급 기능
MySQL에서 SELECT ~ FOR UPDATE를 사용하면 다른 트랜잭션에서 읽기나 쓰기를 시도할 경우 해당 행이 잠금이 해제될 때까지 대기하게 되는데 MySQL 8.0에서는 이를 보완하고 동시성을 효율적으로 처리하기 위해 다음과 같은 기능이 추가되었습니다.
1. NO WAIT
해당 기능은 잠금된 행을 만나면 대기하지 않고 즉시 예외(Lock wait timeout exceeded)를 던집니다.
2. SKIP LOCKED
해당 기능은 잠금되지 않은 행만을 대상으로 작업을 수행하기 때문에 병목을 줄일 수 있습니다.
3. LOCK IN SHARE MODE
해당 기능은 잠금된 행을 다른 트랜잭션에서 읽기는 가능하지만 쓰기 및 삭제가 불가능하게 됩니다.
선착순 쿠폰 발급 로직
이번 로직은 한정된 쿠폰을 여러 사용자가 발급 신청할 때 안정적으로 쿠폰을 발급하기 위한 로직을 구현하는 것입니다.
1. 중복 발급 방지
가장 첫 번째로 사용자가 이미 쿠폰을 발급받았는지 확인합니다.
NO WAIT 기능을 활용하여 예외가 발생하거나 이미 발급된 사용자가 있다면 로직을 종료합니다.
SELECT *
FROM COUPONS
WHERE USER_ID = 'TEST_1'
AND STATUS = 'ISSUED'
FOR UPDATE NOWAIT;
2. 쿠폰 발급
병렬적으로 트랜잭션이 발생하여도 서로 다른 쿠폰을 할당 받을 수 있습니다.
SELECT *
FROM COUPONS
WHERE STATUS = 'AVAILABLE'
LIMIT 1
FOR UPDATE SKIP LOCKED;
3. 쿠폰 상태 업데이트
잠금을 획득한 사용자만 쿠폰 상태를 업데이트할 수 있기 때문에 다른 트랜잭션의 영향을 받지 않고 안전하게 쿠폰 상태를 업데이트할 수 있습니다.
UPDATE COUPONS
SET STATUS = 'ISSUED',
USER_ID = 'TEST_1'
WHERE ID = 'COUPON_1';
마무리
이와 같은 로직에서는 트랜잭션 관리가 매우 중요한데 이유는 잘못된 트랜잭션 처리로 데드락에 빠질 수 있기 때문에 신중한 설계와 주의가 필요합니다. 또한 이러한 로직은 데이터베이스 단에서 처리되므로 MSA 환경에서도 안전하게 적용할 수 있으며 별도의 외부 캐시 시스템( 뭐... Redis? ) 없이도 효율적인 동시성 제어가 가능합니다.
이 방식은 성능을 유지하면서도 분산 아키텍처에서 안정적으로 동작할 수 있는 좋은 선택이 될 수 있을꺼라고 생각됩니다.
'코딩공부' 카테고리의 다른 글
[Go 기초] 얕은 복사? Error? (0) | 2025.01.22 |
---|---|
AOP를 통한 유지 보수성 향상 - 프로젝트의 매개변수 관리 혁신 (0) | 2024.09.22 |
각 화면의 기능을 공통 인터페이스로 분리 (0) | 2024.09.21 |
[AUIGrid] XSS 취약점 발견 및 해결 과정 (0) | 2024.09.21 |
[Oracle] SQL Function 복습 (0) | 2023.02.26 |