[DB] 트랜잭션

AgileLog·2025년 1월 30일

Connection

  • 데이터베이스와의 물리적 연결을 의미(물리적인 연결 채널)
  • 커넥션 생성에는 비용이 많이 듦: 네트워크 연결 수립, DBMS 인증 등
    → 보통 웹 어플리케이션이 시작될 때, 일정 개수의 커넥션을 생성함. 이를 pool에서 관리하여, 어플리케이션 실행 과정 중 커넥션을 이용해야 할때 pool에서 가져와 쓰고 반환하는 방식

Session

  • 데이터베이스와의 논리적 연결을 의미
  • 하나의 세션에서는 하나 이상의 트랜잭션이 수행
  • 아래와 같이, 하나의 세션 안에서 여러개의 트랜잭션이 수행될 수도 있음
-- 트랜잭션 1
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 트랜잭션 2 (같은 세션에서 새로운 트랜잭션 시작)
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Transaction

  • 원자적으로 수행되어야 하는 operation들의 묶음
  • ACID라는 4가지 속성을 만족시킴으로서, 데이터 무결성을 보장
    • Atomicity: 원자성. 트랜잭션 내의 작업은 모두 성공하거나 모두 실패해야함
    • Consistency: 일관성. 트랜잭션 전후에 데이터 일관성이 유지 되야함.
      예를 들어, 이체 이후 2개 계좌의 잔액 합은 트랜잭션 전후가 같아야함.
    • Isolation: 격리성. 여러개의 트랜잭션이 존재할때, 서로 간섭하지 못하고 독립적으로 실행되도록 하는 것.
    • Durability: 커밋된 트랜잭션은 DB에 영구적으로 저장됨

Commit & Rollback

  • 하나의 트랜잭션에는 여러 개의 연산이 포함될 수 있으며, 일부 연산에서 실패가 발생할 경우 이전까지 실행된 작업은 모두 rollback(취소)됨
  • 트랜잭션 내의 모든 작업이 성공하면, commit을 통해 정상 반영함
  • auto commit 설정이 켜져있으면, 하나의 sql문이 실행될 때 마다 db에 자동 반영됨. 따라서, 단순 조회나 로그 기록 등의 작업에는 적절하나, 은행 이체 거래와 같이 여러 작업을 하나의 트랜잭션에 묶어야 하는 경우에는 위험함

DB 동시성 제어

  • 동일한 데이터에 접근하는 DB 트랜잭션이 동시에 발생할 수 있는데, 이때 데이터 무결성이 지켜질 수 있도록 제어가 필요함
  • 예를 들어, 티켓팅 예약 기능에서 같은 좌석에 대한 예매 요청이 동시에 온다면 A 트랜잭션에서 해당 좌석에 대한 예약 완료 처리를 하던 도중에, B 트랜잭션이 같은 좌석 데이터에 대해 갱신을 해버릴 수가 있음. 만약 이러한 이슈가 제어되지 않는다면, 하나의 좌석에 대해 예약자가 2명이 발생하는 문제가 생길 수 있음
  • 위처럼, 데이터 정합성을 깨는 중복 데이터가 발생하는 문제가 생길 수도 있지만, 동일한 데이터에 대한 업데이트 연산이라면 아예 덮어쓰기가 되어버려 하나의 작업 자체 내용이 사라져버릴 수도 있음. 이를 갱신 손실 문제라고 함.

트랜잭션 격리수준

트랜잭션의 격리성을 높이면, 데이터 무결성을 높이는데 좋지만, 동시성(성능)을 낮출 수 있음. 동시성 - 격리성은 트레이드 오프 관계로 격리성 수준을 적절히 선택해야함.

각 격리 수준과 관련하여 여러가지 이상 현상이 있음.

** 더티 리드(dirty reads)
: 커밋 되지 않은 데이터까지 읽는 현상으로, 롤백된 데이터를 읽을 수도 있음.

** 팬덤 리드(phantom reads)
: 하나의 트랜잭션 안에 동일한 쿼리가 두 개 이상일때, 각 쿼리의 결과값이 달라지는 현상

** 반복 가능하지 않은 리드(non-repeatable reads)
: 하나의 트랜잭션 안에 같은 레코드에 대한 조회가 두 번 이상 발생할때, 그 값이 달라지는 것. 팬텀 리드와 다른건, "행"을 기준으로 값이 달라지는지에 초점을 둠.

  • READ UNCOMMITTIED
    : 커밋되지 않은 변경 사항도 다른 트랜잭션이 읽을 수 있음
    → 더티리드, 팬텀 리드, 반복 가능하지 않은 리드 모두 발생 가능
    → 동시성은 제일 좋음. 가장 낮은 격리성.
    → ex. 실시간 방문자 수 트랙킹처럼 데이터 정확성은 떨어지더라도, 실시간 대용량 데이터의 추세를 확인하는 기능에서 사용될 수 있음.
  • READ COMMITTED
    : 커밋된 데이터만 읽을 수 있음. 성능과 일관성을 균형있게 보장.
    → 더티리드 방지. 팬텀 리드, 반복 가능하지 않은 리드는 발생 가능
    → RDBMS에서 가장 흔하게 사용되는 격리 수준(ex.PostgreSQL, Oracle의 기본값)

  • REPEATABLE READ
    : READ COMMITTED에서 더 나아가, 트랜잭션 내에서 같은 행을 반복적으로 조회하더라도, 항상 같은 값을 읽도록 보장
    → 더티리드, 반복 가능하지 않은 리드 방지.
    → 새로운 행이 추가되는 것은 상관없으므로, 팬텀 리드는 발생 가능
    → MySQL 8.0 innoDB의 기본값

  • SERIALIZABLE
    : 가장 높은 수준의 격리성으로, 이미 한 트랜잭션이 진행중일때, 다른 트랜잭션이 같은 데이터에 접근하는 것 자체가 방지됨.
    → 더티리드, 팬텀 리드, 반복 가능하지 않은 리드 모두 방지(트랜잭션이 순차적으로 이루어지므로)
    → 금융/회계 시스템 등 데이터 정합성이 매우 중요한 시스템에서 사용.

동시성 제어 기법

  • 락킹: 같은 데이터에 대해 작업을 진행중인 트랜잭션이 있을 경우, 다른 트랜잭션이 접근하지 못하도록 DB락을 적용
  • 타임스탬프: 트랜잭션마다 부여된 타임 스탬프를 기반으로 트랜잭션간 순서를 고려하여 읽기/쓰기 요청을 처리함

Lock

1. 충돌 가능성과 롤백 예외 처리 유무

낙관락

: 충돌 발생 가능성이 거의 없을 것이라 전제하고, 일단 트랜잭션을 진행한 후에
최종 결과를 보고 커밋할지 롤백 및 재시도 등을 할지 결정. 성능 좋음.

비관락

: 락을 취득한 트랜잭션이 진행되는 동안, 임계영역에 접근하려는 다른 트랜잭션을 접근을 막음.

2. 락이 걸린 후, 트랜잭션의 접근 허용 범위

공유락

: 읽기락. 공유 데이터에 대한 동시 읽기는 허용되지만, 쓰기 작업은 금지

배타락

: 공유 데이터에 대한 수정이 이루어지고 있기 때문에, 해당 테이블이나 데이터에 대해 읽기/수정 작업 모두 금지.

DB 데드락

  • "데드락"은 기본적으로 두 개 이상의 작업이 서로의 자원을 획득하기를 기다리면서, 무한 대기 상태로 빠지는 교착 상태
  • MySQL InnoDB 등에서는 데드락이 발생시, DBMS가 이를 탐지해 트랜잭션 중 하나를 강제 종료(롤백)시켜서 자원을 해소하는 방법을 주로 사용

DB 회복(Recovery)

  • 시스템 장애 발생시, 장애 발생 이전의 상태로 복구시키는 작업

  • 대표적으로, 즉시 생신과 지연 갱신이 있음
    즉시 갱신
    트랜잭션이 실행될 때 마다 즉시 DB에 반영하고 이를 로그에도 기록해둠.
    → 장애 발생시, 로그 내용을 기반으로 장애 발생 전 커밋되지 않은 트랜잭션은 롤백시키고(Undo로그 사용), 커밋된 내용은 다시 적용시킴(Redo로그 사용 )

    지연 갱신
    트랜잭션 실행될 때마다 로그에는 기록해두지만, 실제 커밋되기 전까지는 DB에 반영하지 않음
    → 장애 발생시, 로그 내용을 기반으로 커밋된 내용까지만 다시 재적용(Redo)

  • DB 회복 과정에서, 로그를 다시 확인해야하는데 이때 체크포인트라는 개념이 나옴. 체크포인트는 물리적인 저장공간까지 반영 완료된 지점을 나타냄.
    → 체크포인트 이후의 내용에 대해서만 recovery 대상이 됨

스터디 회고

지난 5주간 데이터베이스 스터디를 진행했다. 취준과 병행하다보니, 생각보다 갑자기 겹치는 일정들이 생겨서 과제만 제출한 주도 있었다(이 부분이 좀 아쉽다 ㅠㅠ) 하지만, 매주 과제를 수행하면서 데이터베이스에 대한 필수 이론들을 다시 정리하고 공부해볼 수 있었다. 프로젝트에서 데이터베이스를 많이 사용해봤음에도, 트랜잭션 격리, 회복, 이상 현상, 무결성과 정합성의 차이 등 명확하게 바로 설명하지 못했었다. 스터디를 통해, 데이터베이스에 대한 공부도 다시 해볼 수 있던게 좋았다. 면접은 사실 스터디를 통해, 실력이 엄청 늘었다기엔 너무 짧은 시간이었어서 ... 하지만 적어도 내가 어느 부분에 단점이 있는지는 발견할 수 있는 계기가 되었다.(한번 당황하면 페이스가 확 말린다던지 등) 특히, 멘토님들이 줌 회의실을 돌아다니시면서 면접도 같이 봐주실 때가 있는데, 던져주시는 질문들을 통해서 "내 프로젝트 경험이 이런 부분에서 질문을 받을 수 있겠구나"하는 경험들이 좋았다! 시간적 여유만 맞으면 다른 과목으로 한번 더 해보고 싶다

profile
개발 시행착오 기록장

0개의 댓글