Zayson
A to Zayson!
Zayson
전체 방문자
오늘
어제
  • 분류 전체보기 (132)
    • Computer Science (20)
      • Network (4)
      • DB (12)
      • OS (4)
    • Algorithm (32)
      • 완전탐색(Brute-Force) (3)
      • 그리디(Greedy) (6)
      • 투포인터(Two-Pointer) (1)
      • 그래프(Graph) (5)
      • BFS & DFS (9)
      • 구현, 시뮬레이션(Implementation) (5)
      • 다이나믹 프로그래밍(DP) (3)
    • Backend (51)
      • Spring Boot (19)
      • JPA (16)
      • Kafka (2)
      • Java (13)
      • Kotlin (1)
    • DevOps (1)
      • Jenkins (5)
      • Oracle Cloud Infrastructure (1)
      • Kubernetes & Docker (1)
    • Trouble Shooting (3)
      • JPA (1)
      • Spring Boot (2)
    • 회고 (5)
      • 엔빵 프로젝트 포스트 로드맵 (1)
      • 2022년 (4)
    • Kafka (7)
      • Kafka (5)
      • Kafka Connect (2)
    • 기술 서적 (6)
      • 데이터 중심 애플리케이션 설계 (3)
      • 개발자가 반드시 정복해야할 객체 지향과 디자인 패턴 (2)
      • 가상 면접 사례로 배우는 대규모 시스템 설계 기초 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

인기 글

태그

  • Backend
  • 나 혼자 스프링부트!
  • kafka
  • 프로그래머스
  • 완전탐색
  • Kafka Connect
  • 구현
  • JPA
  • 관계형 데이터베이스 실전 입문
  • dfs
  • spring boot
  • 라이브스터디
  • Java
  • BFS
  • 그리디
  • 엔빵프로젝트
  • CS
  • Computer science
  • 백준
  • SpringBoot

최근 글

티스토리

hELLO · Designed By 정상우.
Zayson

A to Zayson!

트랜잭션의 본질 (DB 스터디 7주차)
Computer Science/DB

트랜잭션의 본질 (DB 스터디 7주차)

2022. 11. 3. 12:58
"관계형 데이터베이스 실전 입문 - 오쿠노 마키아"를 읽으며 매주 스터디 진행

목표

  • 트랜잭션의 기본을 파악
  • RDB에서 트랜잭션을 사용해 데이터 정합성을 보장하는 방법

14.1 트랜잭션

  • 데이터를 올바르게 보장하기 위해 고안된 방법
  • 실제 애플리케이션 개발에서는 관계형 모델(정규화)와 트랜잭션을 모두 구현해야 데이터의 정합성을 보장 가능

트랜잭션의 기능

  • 트랜잭션이 필요한 상황
    • DB 서버에 여러 개의 클라이언트로부터 동시에 엑세스가 발생하는 경우
    • DB 서버 or 애플리케이션이 갱신 처리 도중에 중단되어 데이터 부정합이 발생하는 경우
  • ex) 은행 계좌 입/출금 처리
    • 잔액 100만원, A 트랜잭션은 30만원 입금 처리, B 트랜잭션은 20만원 출금 처리
    1. 트랜잭션 A 잔액 조회 : 100만원
    2. 트랜잭션 B 잔액 조회 : 100만원
    3. 트랜잭션 A 30만원 입금 처리 및 커밋 : A가 읽은 100만원에서 30만원 입금 처리 = 130만원
    4. 트랜잭션 B 20만원 출금 처리 및 커밋 : B가 읽은 100만원에서 20만원 출금 처리 = 80만원
    5. 최종 잔액 80만원

동시 실행 제어

  • 위의 예제에서 발생한 문제는 A 트랜잭션과 B 트랜잭션이 데이터에 동시에 엑세스 하면서 발생한 문제이다. → 트랜잭션 처리가 되었다고 할 수 없다.
  • 트랜잭션 처리를 통해 동시에 엑세스 하는 작업을 제어하는 것이 가능하다.

크래시 복구

  • 작업을 처리하는 도중에 에러가 발생하는 경우 데이터를 올바르게 유지하는 것이 중요하다.
  • 트랜잭션이 없는 경우 에러 발생 시 작업이 어디까지 처리되었는지 추적하는 것이 어렵다.
    • 작업 추적을 위한 추가적인 로직을 개발해야한다.
  • 트랜잭션은 비정상적으로 중단된 처리를 이전 작업으로 롤백하는 것이 가능하다.
  • 트랜잭션은 DB 서버가 크래시돼도 재기동하면 필요한 복구 작업을 수행

트랜잭션의 키, 스케줄

처리의 병렬화는 필수불가결

  • 애플리케이션 작업을 싱글 스레드 방식으로 처리하는 것은 데이터의 부정합이 일어나지 않지만 성능 효율이 낮아진다.
  • 애플리케이션 작업을 멀티 스레드 방식으로 처리하는 것은 최근 개발에서 필수적이다.
  • 실제 DB에 수백, 수천개의 트랜잭션이 동시에 수행되는 것이 일반적이다.

동시 실행 제한의 키, 스케줄

  • 트랜잭션이 동시에 실행되는 경우 데이터가 정확하다고 보장하는 것은 스케줄이다.
  • 트랜잭션은 일련의 작업을 정리한 것 → 데이터에 대한 읽기나 쓰기 조작을 분해 가능
  • 각 트랜잭션의 순서를 지정하는 것이 스케줄
  • 쓰기 처리의 경우 트랜잭션이 동시에 실행될 때 다른 트랜잭션이 읽은 데이터에 영향을 미칠 수 있다.
  • 서로의 트랜잭션에 영향을 미치거나 간섭하는 지 파악하고 영향을 주지 않게 스케줄링 하는 것이 트랜잭션 병렬 처리의 주 목적
💭 데이터의 정확성

✔️ 데이터가 올바르게 유지되는 상태란 개별 트랜잭션을 한 개씩 차례로 실행할 때와 동일한 결과를 나타내는 경우
✔️ 개별 트랜잭션을 직렬로 실행할 때 나오는 결과 = 병렬로 실행해도 영향이 없는 것 = 데이터가 올바르게 유지됨

스케줄러의 성능

  • 직렬화된 스케줄과 같은 결과가 나오는 스케줄은 조합에 따라 많이 존재할 수 있다.
  • 가장 적합한 스케줄을 선택하는 것이 스케줄러의 임무
  • 스케줄러의 성능을 고려 시 중요한 점
    • 얼마나 많은 트랜잭션을 병렬화할 수 있는가? → 병렬화를 많이 할 수록 좋다.
    • 최적의 스케줄을 찾는 데 필요한 비용
      • 여러 개의 트랜잭션이 있을 때 동시에 실행할 수 있는 조합 중 최적의 조합을 찾는다면 조합을 찾는 비용이 많이 든다.
      • 적당한 계산 비용으로 적당한 스케줄을 구하는 방식을 선택

14.2 트랜잭션의 특징

ACID란?

  • ACID란 트랜잭션이 갖춰야할 필수 성질

원자성 (Atomicitiy)

  • 트랜잭션에 포함된 모든 작업이 성공(Commit) 또는 실패(Abort)하는 성질
  • SQL에서는 실패한 경우를 롤백(Rollback)이라고 한다.
  • 애플리케이션은 트랜잭션이 처리된 이후 성공/실패 두 가지의 상태만 확인하면 되며, 에러 처리가 단순해진다.
  • 원자성이 보장되지 않는 경우
    • 트랜잭션 내 몇 번째 작업부터 다시 시작해야하는지 모른다.
    • 원래 작업으로 돌려야 하는지에 대해 일일히 작성이 필요하다.
  • 트랜잭션이 실패할 확률이 0%가 아니기 때문에 애플리케이션 단에서 실패 시 재처리 로직같은 추가적인 코드 작성이 필요 (리트라이)

일관성 (Consistency)

  • 트랜잭션을 실시한 전후에는 데이터의 일관성이 손상되지 않아야 하는 성질
  • 트랜잭션 실행 전 DB의 상태가 일관적 = 데이터의 부정합이 없는 것
  • 트랜잭션 실행 후 DB의 상태가 일관적 = 데이터의 변경은 있지만 일관성은 유지하는 것
    • 트랜잭션 실행 시 A상태의 일관성 → B 상태의 일관성으로 변경
  • DB 자체가 데이터의 의미를 아는 것이 아니기 때문에 데이터의 일관성이 유지되었는지 판단하는 것은 애플리케이션이 해야할 역할
    • 트랜잭션의 기능만으로 일관성을 보장하기 어렵다.

격리성 (Isolation)

  • 동시에 실행하는 여러 개의 트랜잭션이 서로 영향을 주지 않는 성질
  • 개별 트랜잭션의 실행 결과는 트랜잭션을 직렬로 실행했을 때와 결과가 같아야 한다.
  • 격리성을 해치는 스케줄은 스케줄러가 제거, 문제 생기는 경우 롤백 수행 가능

영속성 (Durability)

  • 일단 커밋이 완료된 트랜잭션이 손상되지 않는 성질
  • 확정된 트랜잭션을 취소할 수 없다.
  • 시스템 크래시가 발생해도 크래시 전에 커밋한 데이터로 복원 가능

다양한 비정상 상태

  • ACID는 트랜잭션이 가져야 하는 성질
  • 비정상 상태 (Anomaly = 이상현상)는 트랜잭션이 있어서는 안되는 상태

갱신 분실 (Lost Update)

  • B 트랜잭션이 A 트랜잭션이 갱신하기 전의 데이터를 기준으로 갱신하는 경우 A 트랜잭션이 갱신한 데이터는 유실된다.
  • ex) 하나의 계좌에서 입/출금이 이뤄지는 경우 (위에서 든 예시가 대표적인 갱신 분실 예)
    • A 트랜잭션이 입금 처리 커밋
    • B 트랜잭션은 A 트랜잭션이 입금 처리하기 전 데이터에 대해 갱신 처리 커밋
    • A 트랜잭션이 갱신한 금액이 사라짐

모순적 판독 (Inconsistent Read)

  • 어떤 트랜잭션의 실행 결과가 다른 트랜잭션의 실행 결과에 영향을 주면 데이터의 정합성이 보장되지 않는다.
  • 한 트랜잭션이 값을 갱신하는 사이에 다른 트랜잭션이 어떤 것은 갱신 이전 값, 어떤 것은 갱신 이후 값을 읽어 데이터의 불일치가 발생하는 것
    • A 트랜잭션이 1번, 2번 데이터를 읽고 1번 데이터에 대한 갱신
    • A 트랜잭션 작업 중간에 B 트랜잭션이 1번(갱신 O), 2번(갱신 X) 데이터를 읽어 자신의 작업 처리
    • A 트랜잭션이 2번 데이터 갱신 + 커밋 진행
    • B 트랜잭션은 갱신 이전, 이후 값을 읽어 작업을 처리했으므로 데이터 부정합 발생

더티 리드 (Dirty Read)

  • 아직 커밋되지 않은 데이터를 읽음으로써 발생하는 비정상 상태
  • A 트랜잭션이 갱신한 이후 (커밋 전)에 B 트랜잭션이 해당 데이터를 읽을 때, A 트랜잭션이 실패해 롤백이 발생하는 경우 B 트랜잭션은 잘못된 데이터를 읽어서 사용하기 때문에 문제 발생
    • A 트랜잭션이 데이터 갱신 (커밋 X)
    • B 트랜잭션이 해당 데이터를 읽어서 자신의 작업 처리 (갱신 O, 커밋 X)
    • A 트랜잭션에서 에러가 발생해 롤백
    • B 트랜잭션은 롤백되기 전 데이터에 대해서 읽어서 작업을 처리해야 하지만, 실제로는 A에서 갱신이 일어난 잘못된 데이터를 읽어 작업 처리

논 리피터블 리드 (Non Repeatable Read)

  • 한 개의 트랜잭션에 같은 데이터 항목을 여러 번 읽을 때 그 트랜잭션이 쓰기를 하지 않았어도 바뀐 값을 읽는 현상
    • A 트랜잭션이 1번 데이터를 읽음 (커밋 이전)
    • B 트랜잭션이 1번 데이터에 대해서 갱신 및 커밋
    • A 트랜잭션이 1번 데이터를 읽을 때 B 트랜잭션이 갱신한 값으로 읽음
    • 최초 A 트랜잭션이 읽은 데이터 ≠ 마지막에 A 트랜잭션이 읽은 데이터

팬텀 리드 (Phantom Read)

  • 범위 검색에서 발생하는 문제
  • 기존 데이터 항목 값에 이상을 일으키는 것이 아니라 과거에 없던 데이터가 나오는 것
    • 전체 테이블 행이 5개인 행 기준
    • A 트랜잭션이 테이블 내 데이터 전체 조회 → 5개의 행 조회 (커밋 이전)
    • B 트랜잭션이 테이블에 1개의 데이터 추가 → 현재 테이블에는 6개의 행
    • A 트랜잭션이 테이블 내 데이터 전체 조회 → 6개의 행 조회 (커밋)
    • 최초 A 트랜잭션이 읽은 전체 데이터 개수 ≠ 마지막에 A 트랜잭션이 읽은 전체 데이터 개수

스케줄과 락

  • 갱신 분실, 모순성, 더티 리드, 논 리피터블 리드, 팬텀 리드와 같은 이상현상은 트랜잭션의 동시성에서 발생할 수 있는 문제
  • 이상현상이 발생하지 않도록 트랜잭션의 순서를 결정할 필요 존재 = 트랜잭션 스케줄

락킹 스케줄

  • 쿼리의 실행에 따라 트랜잭션 내 데이터 일관성이 무너지지 않도록 작업 대상이 되는 행에 대해 그 작업이 수행되기 전에 락을 거는 방법
  • 락을 이용해 경쟁 상태에 있는 트랜잭션 (동일한 데이터에 접근하려고 경쟁하는 트랜잭션)의 엑세스를 막아준다. → 데이터의 무결성이 유지된다.
    • A 트랜잭션, B 트랜잭션 모두 데이터에 대해 갱신하려는 경우
    • A 트랜잭션이 데이터에 대한 락을 걸음
    • B 트랜잭션은 데이터에 엑세스 하지 못하고 대기
    • A 트랜잭션이 이용하고 락을 해제
    • B 트랜잭션은 데이터를 읽고 자신의 작업 처리

교착 상태 (데드락, Deadlock)

  • 트랜잭션이 필요로 하는 데이터 항목을 순서대로 잠그는 아키텍처는 데드락 문제 발생 가능성 존재
  • 행 (레코드)에 대한 락, 페이지 수준의 락이 구현된 경우 발생할 수 있다.
    • A 트랜잭션이 1번 데이터에 대해 락을 걸고 작업 처리 (커밋 이전)
    • B 트랜잭션이 2번 데이터에 대해 락을 걸고 작업 처리 (커밋 이전)
    • A 트랜잭션이 2번 데이터를 사용하기 위해 락을 걸려고 시도하지만 실패
    • B 트랜잭션이 1번 데이터를 사용하기 위해 락을 걸려고 시도하지만 실패

  • A 트랜잭션, B 트랜잭션 모두 자신의 작업을 처리 하지 못한다.
  • 데드락이 발생할 수 있는 경우 락킹을 사용하지 않으면 데이터 부정합이 일어날 수 있는 트랜잭션이다.
  • 데드락 해결 방법
    • 데드락 감지 시 양쪽 트랜잭션 모두 롤백, 한쪽만 롤백
    • 어떤 기준으로 롤백할 트랜잭션을 결정할 것인가 ?
    • 타임아웃까지 기다리는 방법
  • 데드락에 대한 오류처리가 필요하다.

트랜잭션 격리 수준

  • 트랜잭션의 격리 수준이 높아질 수록 직렬화된 스케줄과 동일한 결과를 보장할 확률이 높다.
  • SERIALIZABLE의 경우 직렬화된 스케줄과 동일한 결과를 보장한다.
  • 하지만, 락을 많이 사용해서 처리하기 때문에 병렬처리의 어려움으로 인한 성능 저하가 발생한다.
  • 락을 많이 이용하기 때문에 데드락도 발생할 가능성이 많아진다.
  • 격리 수준을 선정하는 가장 큰 키포인트는 애플리케이션 레벨에서 해당 격리 수준에서 발생할 수 있는 이상현상에 대응할 수 있는가이다
  • SERIALIZABLE 이외 격리 수준은 명시적인 잠금을 통해 이상현상을 방지할 수 있다.

명시적인 잠금

select ... for update 구문을 의미한다.
select 하는 레코드에 쓰기 잠금(Exclusive-Lock, X-lock)을 거는 것

MVCC (Multi Version Concurrency Control)

  • 락킹을 통한 직렬적인 방식은 병렬 처리가 되지 않기 때문에 성능 저하 발생
  • 여러 개의 트랜잭션이 병렬적으로 처리하면서 어떤 트랜잭션이 갱신한 데이터에 대해 다른 트랜잭션은 갱신 이전 버전의 데이터를 읽어 동시성을 제어하는 기법
  • MVCC의 이전 버전은 롤백 세그먼트 (UNDO 영역)에 저장된다.
  • SELECT 쿼리가 발생할 때 실제 데이터 레코드에서 조회하는 것이 아닌 롤백 세그먼트에서 데이터를 조회한다.
  • 갱신을 포함하지 않고 참조만 있는 트랜잭션은 MVCC를 이용해 데이터의 부정합이 발생하지 않으면서 성능을 개선할 수 있다.
  •  

크래시 복구

  • 데이터의 영속성을 보장하기 위해 DB 서버가 크래시 되더라도 크래시 이전의 데이터로 복구해야한다.
  • 커밋한 데이터가 크래시에 의해 손상될 수도 있다.
  • 크래시 복구 절차
    1. 스테이블 로그를 이용해 로그 항목을 재생(REDO)하여 DB 캐시를 최신의 상태로 복원
    2. 크래시 한 순간에 완료되지 않은 트랜잭션에 의한 갱신을 취소 (UNDO)
    3. REDO, UNDO를 모두 실행해 크래시 복구 완료

DB 컴포넌트

스테이블 DB : 비휘발성 DB 스토리지
DB 캐시 : 휘발성 메모리에 있는 DB의 서브셋, 갱신 작업은 캐시에서 이뤄지고 스테이블 DB에 플러시된다.
스테이블 로그 : DB 캐시에서 수행된 작업의 내역을 기록한 것, 비휘발성 스토리지에 저장
로그 버퍼 : 스테이블 로그에 적재하기 전에 이용하는 버퍼

14.3 트랜잭션과 데이터 모델의 융합

관계형 모델과 ACID의 ⌜C⌟

  • 트랜잭션을 실행하는 경우 DB는 A (일관성 유지) → B (일관성 유지)로 다른 일관성을 갖는 상태로 전환되는 것
  • DB의 일관성을 보장하는 것은 애플리케이션에 달림
  • 일관성 (제약조건, 규칙을 준수) = 트랜잭션 이후에 데이터가 제약조건, 규칙을 준수해서 표현됨
  • 일관성 유지 판단을 위한 로직은 데이터 모델로 표현되므로 관계형 모델에 대한 이해가 필수

관계형 모델과 이상 현상

  • 관계형 모델의 이상 현상 ≠ 트랜잭션에서 발생 가능한 이상 현상
    • 데이터 부정합 관점에서는 동일
    • 관계형 모델의 이상 현상 : 데이터 자체의 모순
    • 트랜잭션의 이상 현상 : 같은 시간에 여러 작업 처리 수행 시 발생 문제
      • 행의 데이터 변경, 행의 추가, 행의 감소 등
      • 트랜잭션의 이상 현상이 발생하면 릴레이션 연산에 따른 결과가 올바르다고 보장 X
  • 트랜잭션 이상 현상 해결 위해 SERIALIZABLE 격리 수준 설정, 참조만 하는 트랜잭션의 경우 MVCC 설정 등 릴레이션 연산이 올바른 결과를 보장하도록 설정 필요

정규화와 직교성

  • 트랜잭션이 올바르게 처리되어 데이터가 갱신되더라도 실제 데이터의 중복으로 인해 데이터 부정합 발생 가능
  • 트랜잭션이 이상현상 없이 처리되도록 설정 + 릴레이션의 정규화, 직교성을 구현 = 데이터 정합성 보장, 일관성 보장, 이상 상태 발생하지 않도록 줄이는 것이 가능

제약

데이터 모델만으로 충분하지 않은 이유

  • 데이터 모델은 도구
  • 애플리케이션 레벨에서 로직 미스로 인한 버그 발생, 데이터 모델의 잘못된 구현 등 의도하지 않은 작업이 처리될 수 있다.
  • 이는 트랜잭션의 결과가 올바르지 않음을 의미
  • 처리에서의 문제가 발생할 수 있기 때문에 정합성을 지키기 위해 노력 → 제약조건

제약을 활용해 데이터를 보호

  • 제약 (Constraint) : 올바른 데이터가 어떤 방식으로 존재해야 하는지 표현
  • 데이터 정합성을 보장하기 위해 이중, 삼중으로 방어 필요
    • 정규화, 직교화를 이용한 관계형 모델의 올바른 구현
    • 트랜잭션 작업의 이상현상 처리
    • 제약을 이용한 애플리케이션 로직, 릴레이션 연산 등에서 발생할 수 있는 데이터의 부정합 방어

NOT NULL

  • 1NF 테이블에는 NULL이 포함되면 안된다.
  • NULL이 포함되지 않도록 하기 위해 NOT NULL 제약 조건 이용

고유성 제약

  • 테이블에서 어떤 컬럼의 조합에 중복이 없음을 보장하는 제약조건
  • 후보키가 될 수 있는 컬럼의 조합 모두에 기본키 또는 유니크 인덱스 작성

CREATE TYPE

  • SQL에서 지원하는 타입보다 좁은 범위의 집합을 도메인으로 정의하거나 새로운 데이터 유형을 정의하는 경우 사용

CHECK 제약

  • 컬럼의 데이터 범위를 세밀하고, 현시점의 테이블 상태에 맞춰 제약하는 조건
    • ex) 한 컬럼 값에 YES, NO만 들어오도록 지정
  • RDBMS마다 지원 상황 다름

외부키 제약

  • 테이블 사이에 데이터 정합성을 확인하는 제약
  • 외부키 제약을 통해 자식 테이블에 있는 키와 같은 값의 키가 부모 테이블에 존재하는 제약 표현 가능
  • 외부키 제약 사용하지 않는 경우에는 애플리케이션 레벨에서 제약을 구현
    • 외부키 제약을 이용하는 것보다 애플리케이션 레벨에서 구현하는 것이 성능이 떨어짐
    • 쿼리 호출을 위한 네트워크, SQL의 해석, 운영 유지 등등..

트리거

  • 외부키를 이용해 테이블 사이에 정합성을 보장하지 못하는 경우 존재
    • 테이블의 키와 같은 값의 키가 다른 테이블에 존재하지 않는지 판단
    • 테이블의 키와 같은 값의 키가 여러 테이블 중 하나만 존재하는지 판단
    • 테이블의 키와 같은 값의 키가 N개이상 혹은 미만 존재 판단
  • 트리거 : 테이블 사이의 복잡한 제약 표현 하는데 사용
    • 행 트리거 : 행 마다 데이터 조작을 실행
    • 문장 트리거 : SQL 문마다 실행
    • 제약 표현에는 행 트리거가 적합

14.4 요약

  • DB에서 가장 중요한 것은 데이터 정합성
  • 데이터 정합성 유지를 위해 트랜잭션, 관계형 모델의 정규화, 직교화를 이용해 데이터 정합성 보장
  • 제약, MVCC, 격리 수준, 락킹 등을 통해 데이터 정합성 추가 보장
반응형
저작자표시 비영리 변경금지 (새창열림)

'Computer Science > DB' 카테고리의 다른 글

웹 응용프로그램을 위한 데이터 구조 (DB 스터디 6주차)  (0) 2022.11.02
인덱스 설계 전략 (DB 스터디 5주차)  (0) 2022.10.21
이력 데이터와 친해지기 (DB 스터디 4주차)  (0) 2022.10.21
SELECT를 공략하자 (DB 스터디 4주차)  (0) 2022.10.21
정규화 이론(두번째) - 결합 종속성 (DB 스터디 3주차)  (0) 2022.09.28
    'Computer Science/DB' 카테고리의 다른 글
    • 웹 응용프로그램을 위한 데이터 구조 (DB 스터디 6주차)
    • 인덱스 설계 전략 (DB 스터디 5주차)
    • 이력 데이터와 친해지기 (DB 스터디 4주차)
    • SELECT를 공략하자 (DB 스터디 4주차)
    Zayson
    Zayson
    공부한 내용을 정리하는 공간

    티스토리툴바