레이스 컨디션(Race Condition)이란?
cleanUrl: /레이스-컨디션-이란? floatFirstTOC: right
레이스 컨디션(Race Condition)이란?
레이스 컨디션이 왜 위험할까?
await this.dataSource.transaction(async (manager) => { // 좌석 정보 조회 (락을 걸지 않음) const seat = await manager.findOne(Seat, { where: { id: seatId } }); if (seat.isReserved) { throw new Error('이미 예약된 좌석입니다.'); } // 좌석 예약 상태 변경 seat.isReserved = true; await manager.save(seat); });
레이스 컨디션을 예방하는 방법
1. 낙관적 락(Optimistic Lock)
- 데이터를 읽을 때, 현재 버전 정보(Version)를 함께 조회한다.
- 데이터를 수정할 때, 조회했던 버전과 현재 데이터의 버전이 동일한지 확인한다.
- 만약 버전이 변경되었다면, 다른 트랜잭션에서 먼저 데이터를 수정한 것이므로 예외를 발생시킨다.
@Version 데코레이터를 이용하면 자동으로 버전 관리를 할 수 있다.import { Entity, PrimaryGeneratedColumn, Column, Version } from 'typeorm'; @Entity() export class Seat { @PrimaryGeneratedColumn() id: number; @Column({ default: false }) isReserved: boolean; @Version() // 낙관적 락 적용 (자동으로 버전 관리) version: number; }
await this.dataSource.transaction(async (manager) => { // 좌석 정보 조회 (락을 걸지 않음) const seat = await manager.findOne(Seat, { where: { id: seatId } }); if (seat.isReserved) { throw new Error('이미 예약된 좌석입니다.'); } // 동시에 다른 트랜잭션이 변경하면 예외 발생 (버전 체크) seat.isReserved = true; await manager.save(seat); });
@Version 필드는 데이터가 변경될 때마다 자동으로 1씩 증가하며, UPDATE시 버전이 다르면 TypeORM에서 자동으로 예외(OptimisticLockVersionMismatchError)를 발생시켜 충돌을 감지한다.2. 비관적 락(Pessimistic Lock)
await this.dataSource.transaction(async (manager) => { // 좌석 정보를 가져옴 (pessimistic_write 잠금 사용) const seat = await manager.findOne(Seat, { where: { id: seatId }, lock: { mode: "pessimistic_write" } }); // 좌석이 이미 예약되었는지 확인 if (seat.isReserved) { throw new Error('이미 예약된 좌석입니다.'); } // 좌석 예약 상태 업데이트 seat.isReserved = true; await manager.save(seat); });
pessimistic_write 모드를 사용하여 비관적 락을 적용할 수 있다.참고 자료

교착 상태(Deadlock)
세상을 위한 바른 기술

Documentation | NestJS - A progressive Node.js framework
Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).
[Nest.js][동시성 문제] Transaction 사용과 통 Lock 걸어버리기
코드 Back-End: Nest.js - boards.service.ts async joinGroup(boardId: number, userId: number) { const board = await this.getBoard(boardId); const boardJoinInfo = await this.joinRepository.find({ where: { boardId }, }); if (board.joinLimit { if (join.userId === userId) { throw new ConflictException('이미 join 했습니다.'); } }); const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.conn..
[NestJS] - 21. 결제 프로세스와 Transaction Isolation
서비스하고있는 많은 플랫폼들은 결제 프로세스를 사용한다. 이번에는 클라이언트측에서 결제 요청 후 백엔드 서버에서의 처리에 대해서 포스팅해보려고 한다. https://sjh9708.tistory.com/50 [Web] 결제 프로세스 적용을 위한 IamPort 사용해보기 우리는 흔히 웹, 키오스크, 모바일 등에서 결제 시스템을 이용하게 된다. 결제 프로세스에 적용을 위한 개념과 간단한 세팅 하는 것을 다루어보려고 한다. 결제 과정 1. 구매자가 구매 상품과 금 sjh9708.tistory.com 해당 포스팅에서 IamPort를 통한 결제 적용과 간단한 프론트엔드 코드를 작성했었다. 프론트엔드에서 결제 완료 후 결제 정보와 함께 벡엔드 서버로 요청을 하게 되는데, 결제 완료에 대한 기록을 남기고, 사용자에게 ..
[typeORM/Nest.js] 정산(@Cron)에 사용하는 락
pessimistic_partial_write vs pessimistic_write
