포스트

Database

데이터베이스 트랜잭션을 어떻게 봐야 하는가

트랜잭션이란

트랜잭션은 여러 작업을 하나의 논리적 단위로 묶어서, 전부 성공하거나 전부 실패하도록 다루는 메커니즘이다.

실무에서 트랜잭션은 단순히 BEGIN, COMMIT 문법이 아니라 “어디까지를 하나의 일관된 작업으로 볼 것인가”를 정하는 설계 도구다.

왜 필요한가

  • 중간 실패 시 데이터가 반쯤 반영되면 안 된다.
  • 동시에 여러 요청이 들어올 때 정합성을 지켜야 한다.
  • 장애 후에도 커밋된 결과는 남아 있어야 한다.

즉, 트랜잭션은 정합성, 동시성, 복구 문제를 함께 다루는 개념이다.

기본 흐름

  • 시작
  • 읽기/쓰기 수행
  • 필요 시 락 획득
  • 성공 시 commit
  • 실패 시 rollback

이 단순한 흐름 뒤에 실제로는 MVCC, undo log, redo log, lock manager 같은 메커니즘이 붙어 있다.

autocommit을 주의해야 한다

MySQL은 새 커넥션의 세션을 autocommit이 켜진 상태로 시작하고, 이때 SQL 한 문장이 하나의 트랜잭션이 되어 오류가 없으면 바로 커밋된다. MySQL: autocommit, Commit, and Rollback 그래서 애플리케이션에서 “여러 문장이 하나의 작업”이라면 START TRANSACTION처럼 명시적 트랜잭션 경계를 반드시 잡아야 한다.

트랜잭션에서 자주 발생하는 문제

  • lost update
  • non-repeatable read
  • phantom read
  • deadlock

이 문제들은 격리 수준과 락 전략 선택으로 이어진다.

좋은 트랜잭션의 조건

  • 짧다
  • 외부 API 호출을 포함하지 않는다
  • 필요한 자원만 잠근다
  • 경계가 명확하다

트랜잭션 안에서 네트워크 호출을 오래 잡고 있으면 락 대기와 데드락 가능성이 크게 올라간다. 네트워크 호출과 DB 트랜잭션을 분리한 사례는 Airbnb 결제 시스템 리뷰에서 다뤘다.

실무 체크포인트

  • 이 작업이 정말 하나의 트랜잭션이어야 하는가
  • 실패 시 어디까지 롤백해야 하는가
  • 어떤 읽기/쓰기 경쟁이 존재하는가
  • 락이 걸리는 범위를 예측할 수 있는가

정리

트랜잭션은 DB 기능이면서 동시에 애플리케이션 경계 설계다. 경계를 넓게 잡으면 락을 오래 쥐고, 좁게 잡으면 중간 실패 때 반쯤 반영된 데이터가 남는다. 위 체크포인트는 그 사이의 경계를 정하기 위한 질문이다.

참고

데이터베이스 내부와 트랜잭션
이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

변경이력

3번 수정

  1. docs(notes): cite sources and ease reading in transaction
  2. docs(posts): normalize common note metadata and headings
  3. docs(posts): rewrite database notes collection

댓글

아직 댓글이 없습니다