dev.syw

여러 작업을 안전하게 묶고, 동시성 문제를 다루는 방법.

트랜잭션과 잠금

은행 송금처럼 "출금"과 "입금"이 함께 성공하거나 함께 실패해야 하는 작업이 있습니다. 이렇게 여러 명령을 하나의 단위로 묶어 안전하게 처리하는 것이 트랜잭션입니다. 동시에 여러 사용자가 같은 데이터를 다룰 때의 잠금과 격리 수준까지 함께 배웁니다.

학습 목표

  • 트랜잭션의 ACID 성질을 이해합니다.
  • BEGIN/COMMIT/ROLLBACK 으로 트랜잭션을 제어합니다.
  • 격리 수준과 동시성 문제를 파악합니다.
  • 교착상태(deadlock)와 TRY...CATCH 오류 처리를 익힙니다.

ACID

성질의미
원자성(Atomicity)전부 성공하거나 전부 실패
일관성(Consistency)제약을 지켜 항상 유효한 상태 유지
격리성(Isolation)동시 트랜잭션이 서로 간섭하지 않음
지속성(Durability)커밋된 결과는 장애에도 보존

BEGIN / COMMIT / ROLLBACK

BEGIN TRANSACTION;

UPDATE Accounts SET balance = balance - 10000 WHERE id = 1;  -- 출금
UPDATE Accounts SET balance = balance + 10000 WHERE id = 2;  -- 입금

COMMIT;        -- 둘 다 성공하면 확정
-- ROLLBACK;   -- 문제가 생기면 전체 취소

COMMIT 전까지의 변경은 임시 상태이며, ROLLBACK 하면 트랜잭션 시작 시점으로 되돌아갑니다.

TRY...CATCH 로 안전하게

BEGIN TRY
  BEGIN TRANSACTION;

  UPDATE Accounts SET balance = balance - 10000 WHERE id = 1;
  UPDATE Accounts SET balance = balance + 10000 WHERE id = 2;

  COMMIT;
END TRY
BEGIN CATCH
  IF @@TRANCOUNT > 0
    ROLLBACK;

  -- 오류 정보 확인 후 다시 던지기
  THROW;
END CATCH;

💡 TIP@@TRANCOUNT 는 현재 열린 트랜잭션 수입니다. CATCH 블록에서 0보다 클 때만 ROLLBACK 하면, 이미 롤백된 상태에서 다시 롤백을 시도하는 오류를 피할 수 있습니다.

격리 수준과 동시성 문제

여러 트랜잭션이 동시에 돌면 다음 문제가 생길 수 있습니다.

문제설명
Dirty Read커밋 안 된 남의 변경을 읽음
Non-repeatable Read같은 행을 다시 읽으니 값이 바뀜
Phantom Read같은 조건 재조회 시 행 수가 달라짐

격리 수준은 이 문제들을 어디까지 막을지 정합니다.

격리 수준DirtyNon-repeatablePhantom
READ UNCOMMITTED허용허용허용
READ COMMITTED (기본)차단허용허용
REPEATABLE READ차단차단허용
SERIALIZABLE차단차단차단
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

⚠️ 주의READ UNCOMMITTED(또는 WITH (NOLOCK))는 잠금을 피해 빠르지만, 커밋되지 않은 잘못된 값을 읽을 수 있습니다. 정산·금액처럼 정확성이 중요한 조회에는 쓰지 마세요.

교착상태(Deadlock)

두 트랜잭션이 서로가 쥔 자원을 기다리며 영원히 멈추는 상황입니다.

트랜잭션 A: 행1 잠금  행2 대기
트랜잭션 B: 행2 잠금  행1 대기    서로 무한 대기

SQL Server는 교착상태를 감지하면 한쪽을 희생자(victim) 로 선택해 강제 롤백시킵니다(오류 1205). 예방법은 다음과 같습니다.

  • 여러 테이블·행을 항상 같은 순서로 접근합니다.
  • 트랜잭션을 짧게 유지합니다(사용자 입력을 트랜잭션 안에서 기다리지 않기).
  • 교착상태 발생 시 애플리케이션에서 재시도 로직을 둡니다.

요약

  • 트랜잭션은 여러 명령을 원자적으로 묶어 ACID를 보장합니다.
  • BEGIN/COMMIT/ROLLBACK 으로 확정·취소를 제어합니다.
  • TRY...CATCH + @@TRANCOUNT 로 오류 시 안전하게 롤백합니다.
  • 격리 수준이 높을수록 동시성 문제는 줄지만 동시성 성능은 떨어집니다.
  • 교착상태는 접근 순서 통일과 짧은 트랜잭션, 재시도로 대응합니다.

연습문제

  1. 두 계좌 간 송금을 하나의 트랜잭션으로 작성하세요.
  2. 위 송금을 TRY...CATCH 로 감싸 오류 시 롤백하도록 만드세요.
  3. Dirty Read·Non-repeatable Read·Phantom Read를 각각 한 문장으로 설명하세요.
  4. 교착상태를 예방하는 방법을 두 가지 이상 적어 보세요.

힌트 — 2번은 BEGIN CATCH 에서 IF @@TRANCOUNT > 0 ROLLBACK;, 4번은 접근 순서 통일·짧은 트랜잭션을 떠올리세요.

💡 연습문제 풀이

불러오는 중…

함께 보면 좋은 자료

댓글 0

MSSQL” 강좌에 대한 댓글입니다.

댓글을 작성하려면 로그인이 필요합니다.