데이터베이스 관련 질문

고객님의 문의에 답변하는 직원은 고객 여러분의 가족 중 한 사람일 수 있습니다.
고객의 언어폭력(비하, 조롱, 욕설, 협박, 성희롱 등)으로부터 직원을 보호하기 위해
관련 법에 따라 수사기관에 필요한 조치를 요구할 수 있으며, 형법에 의해 처벌 대상이 될 수 있습니다.

커뮤니티 이용 정책에 위배되는 게시물을 작성할 경우, 별도 안내 없이 게시물 삭제 또는 커뮤니티 이용이 제한될 수 있습니다.

문의 응대 : 평일 오전 10시 ~ 오후 6시
문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족하거나 응대시간 외 문의하는 경우 확인 및 답변이 지연될 수 있습니다.

  • 뒤끝 SDK 버전 :
  • 프로젝트명 : 프로젝트D
  • 스테이터스 코드 :
  • 에러 코드 :
  • 에러 메시지 :

신규 데이터베이스 트랜잭션 기능을 테스트 중인데, 조건절 동작 방식 관련해서 문의드립니다.

A 테이블에서 재화를 차감할 때
point >= 10 인 경우에만 차감되도록 조건을 걸고,
동시에 B 테이블의 점수를 증가시키는 트랜잭션을 아래와 같이 구성했습니다.

var result = await DBClient.Transaction()
    .From<A>()
        .Where(x => x.InDate == BackEnd.Backend.UserInDate)
        .Where(x => x.point >= 10)
        .Dec(x => x.point, 10)

    .From<B>()
        .Where(x => x.Id == b.Id)
        .Inc(x => x.score, 100)
        .Update()

    .Commit();

그런데 A 테이블의 point가 10 미만인 경우에도
조건을 무시하고 차감 및 B 테이블 업데이트가 함께 수행되는 것으로 보입니다.

반면, 단순 조회에서는 아래와 같이 Where(x => x.point >= 10) 조건이 정상적으로 동작하여
재화가 10 이상인 경우에만 데이터가 조회됩니다.

var userData = await DBClient.From<A>()
    .Where(x => x.InDate == BackEnd.Backend.UserInDate)
    .Where(x => x.point >= 10)
    .FirstOrDefault();

트랜잭션에서의 Where 조건은 조회와 달리
실제 조건 검증(재화 부족 시 트랜잭션 실패)이 아니라
단순 대상 레코드 필터링 용도로만 동작하는 구조인지,
아니면 제가 트랜잭션 조건 사용 방식을 잘못 이해하고 있는 부분이 있는지 확인 부탁드립니다.

안녕하세요 개발자님,
트랜잭션에서 PK 가 아닌 값에 대한 Where절이 무시 되고 있는 것으로 확인됩니다.
해당 현상은 수정을 진행할 예정입니다.

비 PK를 조건에 넣으신 경우 데이터가 많아 질 경우 문제가 발생 할 수 있으니
아래 안내드리는 코드 방식과 같이 선 조건 검색을 이용해 주시면 감사하겠습니다.

// 1. 먼저 조건 확인
var userData = await DBClient.From<A>()
    .Where(x => x.InDate == BackEnd.Backend.UserInDate)
    .FirstOrDefault();

if (userData == null || userData.point < 10)
{
    // 조건 미달 처리
    return new TransactionResult { Success = false, Reason = "포인트 부족" };
}

// 2. 조건이 만족되면 트랜잭션 실행
var result = await DBClient.Transaction()
    .From<A>()
        .Where(x => x.InDate == BackEnd.Backend.UserInDate)
        .Dec(x => x.point, 10)
    .From<B>()
        .Where(x => x.Id == b.Id)
        .Inc(x => x.score, 100)
        .Update()
    .Commit();
좋아요 1

안내해주신 방식대로
선 조회로 조건을 확인한 뒤 트랜잭션에서 차감을 수행하는 구조로 이해했습니다.
다만 이 방식의 경우, 동시 접근 상황에서 레이스 컨디션이 발생할 가능성이 있어 보입니다.

예를 들어,

유저 A의 point가 10인 상태에서
트랜잭션 실행 전 선조회로 point >= 10 조건을 통과한 뒤,
그 사이 다른 트랜잭션에서 point가 차감되고,
이후 현재 트랜잭션에서 Dec(point, 10) 이 수행되면
결과적으로 point가 0 미만으로 내려갈 수 있는 구조로 보입니다.

즉, 조건 검증과 실제 차감이 하나의 원자 연산으로 묶이지 않아
동시성 이슈가 발생할 여지가 있는 것 같습니다.

현재 트랜잭션 API에서
PK 외 컬럼 조건을 포함한 원자적 조건 업데이트
(예: point >= N 인 경우에만 차감하고, 미만일 경우 트랜잭션 실패 처리)
를 지원할 예정이 있는지,
또는 이를 안전하게 처리할 수 있는 권장 구현 방식이 있는지 문의드립니다.

현재 데이터베이스를 활성화한 프로젝트에 대해 서버 픽스가 진행되었습니다.
참고하여 확인 이용해 주시면 감사하겠습니다.

좋아요 1

불가피하게 비 PK 컬럼을 조건으로 사용해야 할 경우가 발생하는데,
이때 원자적 조건 업데이트
(예: point >= N 인 경우에만 차감하고, 미만일 경우 트랜잭션을 실패 처리하는 방식)
를 트랜잭션에서 지원할 예정이 있는지 궁금합니다.

또는 현재 구조에서 이를 동시성 이슈 없이 안전하게 처리할 수 있는
권장 구현 방식이 있다면 함께 안내 부탁드립니다.

정확한 PK 와 같이 비 PK 조건을 사용하시는 경우는
미비한 오버헤드가 존재 하지만 사용 하실 수 있도록 업데이트가 완료되었습니다.

unsigned 타입으로 설정 하여 사용 하시는 경우
Dec 처리 시 실패 처리가 되어 레이스 컨디션이 발생 하지 않고 사용이 가능 합니다.
참고하여 이용해 주시면 감사하겠습니다. :D

좋아요 1