DeJa
Techvu
DeJa
전체 방문자
51,021
오늘
19
어제
54
  • Techvu (60)
    • DesignPatterns (3)
      • 생성 (0)
      • 구조 (1)
      • 행동 (2)
    • Refactoring (0)
    • DataStructures (0)
    • Algorithms (24)
      • 기본 지식 (12)
      • 문제 풀이 (12)
    • OOP (0)
    • TDD (2)
    • DDD (0)
    • Programming Languages (9)
      • Java (9)
      • Kotlin (0)
    • Spring (1)
    • JPA (7)
    • Web (1)
      • 기본 지식 (1)
      • 실무 경험 (0)
    • CS (12)
      • Network (1)
      • OS (8)
      • DataBase (3)
      • Server (0)
    • Git (1)
    • Conferences (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

  • Study
  • GitHub
  • Medium Blog

인기 글

  • 스키마(Schema)
    2022.01.08
    스키마(Schema)
  • 자바 버전별 역사 및 특징
    2022.01.12
    자바 버전별 역사 및 특징
  • 깃허브 사용 방법
    2021.12.15
    깃허브 사용 방법
  • 동시성 이슈(Concurrency Issue)
    2022.03.20
    동시성 이슈(Concurrency Issue)
  • JPA 는 과연 1차 캐시를 통해서 Repeatable R⋯
    2021.12.27
    JPA 는 과연 1차 캐시를 통해서 Repeatable R⋯

태그

  • Spring
  • CS
  • 알고리즘
  • OS
  • network
  • web
  • JPA
  • DATABASE
  • java
  • 디자인패턴
  • TDD

최근 댓글

  • 글 잘읽고 가요.
    아이폰
  • 컴파일러자체에서 꼬리재귀를 지원하지 않으니 static으로⋯
    aaa
  • 압도적 감사
    ㅇㅇㅇ

최근 글

  • Write a test code right now
    2022.03.24
    Write a test code right now
  • 동시성 이슈(Concurrency Issue)
    2022.03.20
    동시성 이슈(Concurrency Issue)
  • POJO, JavaBean, Entity, VO, DTO
    2022.02.08
    POJO, JavaBean, Entity, VO, DTO
  • TDD with Agile
    2022.02.05
    TDD with Agile
  • Java Stream 기초
    2022.01.23
    Java Stream 기초

티스토리

hELLO · Designed By 정상우.
DeJa

Techvu

트랜잭션이란?
CS/DataBase

트랜잭션이란?

2021. 12. 26. 17:51
728x90

트랜잭션(Transacation)

  • 정의
    • 트랜잭션이란 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위라고 할 수 있으며, 트랜잭션에는 여러개의 연산이 수행될 수 있다.
  • 특징
    • 하나의 트랜잭션은 Commit 되거나 Rollback 된다.

트랜잭션을 사용하는 이유

  • 트랜잭션은 하나의 논리적인 작업의 단위이기 때문에, 여러개의 작업을 하나의 논리적인 단위로 묶어서 반영과 복구를 조정할 수 있기 위해 사용한다. 따라서, 데이터의 부정합이 일어났을 경우 롤백을 하여 데이터의 부정합을 방지할 수 있다.
  • Ex. A 계좌에서 출금 -> B 계좌로 입금 하는 것을 하나의 논리적인 작업의 단위로 묶어서 반영과 복구를 조정할 수 있다.

ACID

트랜잭션의 성질에는 ACID 가 있다.

  • Atomicity(원자성)
    • 트랜잭션의 연산은 데이터베이스에 모두 반영되든지 아니면 전혀 반영되지 않아야 한다.
      • All or Nothing
      • Ex. 논리적인 단위를 A, B, C 로 나눴을때 A, B 는 반영되고 C 는 반영되지 않는 경우와 같은 현상은 원자성을 해치는 것이다.
    • 트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느하나라도 오류가 발생하면 데이터베이스 상태를 트랜잭션 작업 이전으로 되돌려서 원자성을 보장
  • Consistency(일관성)
    • 트랜잭션 수행 전과, 수행 완료 후의 상태가 같아야 한다.
    • 상태 : 트랜잭션 수행이 보존해야할 일관성
      • 명시적인 일관성 : 기본 키, 외래 키 등과 같은 무결성 제약조건
        • 무결성 제약조건을 해치지 않는 데이터들에 대해서만 트랜잭션이 성공적으로 수행되어야 한다.
      • 비명시적인 일관성 : Ex. 계좌 이체에서, A 계좌에서 출금이 일어나고 그 돈이 B 계좌로 입금된다 했을 때, 트랜잭션의 전과 후 두 계좌 잔고의 합이 같아야 한다.
  • Isolation(독립성, 격리성)
    • 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수 없다.
    • 수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
    • 격리성은 읽기 일관성과 동시성에 영향을 미치는 성질
  • Durability(영속성, 지속성)
    • 성공적으로 완료된 트랜잭션의 결과는 시스템이 고장나더라도 영구적으로 반영되어야 한다.

트랜잭션 격리 수준

트랜잭션 격리(고립화) 수준이 중요한 이유는, 격리 레벨을 어떻게 설정하느냐에 따라 읽기 일관성이 달라지기 때문이다.

즉, 트랜잭션 격리 수준에 따라 데이터 조회 결과가 달라질 수 있다는 말이다.

이처럼 트랜잭션 격리 수준에 따라 데이터 조회 결과가 달라지게 하는 기술을 MVCC(Multi Version Concurrency Consistency) 라고 한다.

레벨 0 : Read Uncommitted

  • 트랜잭션에서 처리 중인, 아직 커밋 되지 않은 데이터를 다른 트랜잭션에서 읽는 것을 허용
  • Dirty Read, Non-Repeatable Read, Phantom Read 현상 발생
  • Oracle 에서는 이 레벨을 아예 지원하지 않음.
  • MySQL 에서는 설정은 가능

레벨 1 : Read Committed

  • Dirty Read 방지 : 트랜잭션이 커밋되어 확정된 데이터를 읽는 것을 허용
  • 대부분의 DBMS 가 기본 모드로 채택하고 있는 일관성 모드
    • 커밋된 정보만 읽는다.
  • Non-Repeatable Read, Phantom Read 현상은 여전히 발생
  • PostgreSQL, SQL Server 의 경우 읽기 공유 Lock 을 사용해서 구현한다. 하나의 레코드를 읽을 때 Lock 을 설정하고 해당 레코드를 빠져 나가는 순간 Lock 을 해제
  • MySQL(InnoDB) 과 Oracle 은 Lock 을 사용하지 않고 Undo 데이터를 제공하는 방식

RDBMS 에서 MVCC 는 구현 방식에 따라 2가지로 나뉘는데, Pessimistic Lock 을 사용하는 MGA(Multi Generation Architecture) 방식과 Undo Segment 를 사용하는 방식으로 나눠진다.

쉽게 말하면, RDBMS 마다 MVCC 기술을 구현하기 위해서 Lock 을 사용하는 방식을 쓸건지, Undo Segment 에서 데이터를 제공할껀지 선택하여 구현한다.

레벨 2 : Repeatable Read

  • 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때가지 후행 트랜잭션이 갱신하거나 삭제하는 것은 불허함으로써 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴
    • Insert 는 가능
  • Phantom Read 현상은 여전히 발생
  • PostgreSQL, SQL Server 의 경우 트랜잭션 격리 수준을 Repeatable Read 로 변경하면 읽은 데이터에 걸린 공유 Lock 을 커밋할 때까지 유지하는 방식으로 구현
  • Oracle은 이 레벨을 명시적으로 지원하지 않지만 for update 절을 이용해 구현가능.

레벨 3 : Serializable Read

  • 선행 트랜잭션이 읽은 데이터를 후행 트랜잭션이 갱신하거나 삭제하지 못할 뿐만 아니라 중간에 새로운 레코드를 삽입하는 것도 막아줌. 완벽하게 읽기 일관성 모드를 제공
    • INSERT, UPDATE, DELETE 전부 불가능
    • READ 시에 DML 작업이 동시에 진행될 수 없다.

트랜잭션 격리 수준을 설정할 때 발생 하는 문제점들

트랜잭션 격리 수준을 너무 낮게(0 레벨)하면 읽기 일관성을 제대로 보장할 수 없고, 반면 너무 높게하면, 읽기 일관성은 완벽하게 보장하지만 데이터를 처리하는 속도가 느려지게 된다.

  • Read Uncommitted > Read Committed > Repeatable Read > Serializable Read
    • ReadUncommitted 로 갈 수록 동시성은 높아지고, 일관성은 떨어진다.
    • Serializable Read 로 갈 수록 동시성은 떨어지고, 일관성은 높아진다.

따라서, 트랜잭션 격리 수준은 일관성 및 동시성과도 연관이 있다는 것을 알 수있다.

트랜잭션 성질 중 격리성은, 읽기 일관성과 동시성에 영향을 미치는 성질이라고 말할 수 있다.

격리성과 동시성으로부터 파생되는 문제점을 살펴보기 전에, MySQL InnoDB 아키텍처 중 일부에 대해서 배워보자. 지금부터 아래에서 나올 그림들은 MySQL InnoDB 를 기준으로 설명한 그림이다.

InnoDB 버퍼풀, Undo Log, Redo Log

  • InnoDB 버퍼풀
    • 변경된 데이터를 디스크에 반영하기 전까지 잠시 버퍼링 하는 공간
  • Undo Log
    • 변경되기 이전 데이터를 백업 해두는 공간
    • 트랜잭션 보장(Rollback 시 언두 로그에 백업된 데이터 복원)
    • 트랜잭션 격리 수준 보장(트랜잭션 격리 수준에 맞게, 백업된 데이터 반환)
  • Redo Log
    • 변경된 데이터를 백업(Commit 완료된 데이터)
    • 영속성 보장(서버 비정상 종료 시, 리두 로그에 백업된 데이터 복원)

Dirty Read

  • Dirty Read(Uncommitted Dependency)
    • 아직 커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생한다.
      • 데이터를 수정 중인 트랜잭션이 롤백하는 경우
      • 한 트랜잭션(T1)이 데이터에 접근하여 값을 A 에서 B 로 변경하였고 아직 커밋을 하지 않은 상태에서 다른 트랜잭션(T2)이 해당 데이터를 읽는다. T2가 읽은 데이타는 B가 될 것이다. 하지만 T1이 최종 커밋을 하지 않고 종료된다면, T2가 가진 데이타는 꼬이게 된다.
  • MySQL 과 Oracle 에서는 Undo Segment 를 통해서 Dirty Read 문제 해결
    • 만약에, 회사에서 PostgreSQL or SQL Server 등 MVCC 기술을 구현하기 위해 Lock 을 사용하는 DBMS 를 사용한다면 이 부분에 대해서도 잘 알고 있어야 한다.

Dirty Read 는 UPDATE 쿼리문이 커밋되기 전에, 다른 트랜잭션에서 데이터를 읽으면, 코딩이 조회가 된다. 하지만 T1 트랜잭션에 문제가 생겨서 롤백이 되면 T2 가 조회한 값을 가지고 CUD 에 사용하였다면 데이터가 꼬이게 될 것이다.

Non-Repeatable Read

Repeatable Read 의 특징을 반대로 생각하면 된다.

  • Non-Repeatable Read(Inconsistent Read)
    • T1 이 A 테이블을 SELECT 한 후 T2 에서 A 테이블 내용을 UPDATE 한다고 가정.
    • T2 가 해당 변경사항(UPDATE)을 COMMIT 한 이후에, T1 이 다시 A 테이블을 SELECT 하면 변경사항을 읽어들일 수 있음

Phantom Read

  • Phantom Read
    • T1 이 A 테이블에서 SELECT 한 이후 T2 에서 A 테이블에 내용을 추가(INSERT) 한다고 가정.
    • Repeatable Read 가 보장된 경우, A 테이블에서 SELECT 해왔던 데이터들을 T2 가 UPDATE 하여 COMMIT 한 후 T1 에서 다시 A 테이블을 SELECT 하더라도 T2 의 수정 내용을 읽어들일 수 없음
    • 하지만 T2 가 추가/삭제(INSERT)를 한 경우, 다시 A 테이블에서 SELECT 하게 되면 기존 A 에서 SELECT 했던 데이터에서 row 가 추가될 수 있다.(유령 데이터)

References

  • https://feco.tistory.com/45
  • https://brunch.co.kr/@skeks463/27
  • https://coding-factory.tistory.com/226
  • http://wiki.gurubee.net/pages/viewpage.action?pageId=21200923
  • https://www.datanet.co.kr/news/articleView.html?idxno=116534
  • http://haisins.epac.to/wordpress/?p=1083
  • https://mysqldba.tistory.com/335
  • https://steemit.com/kr/@yjiq150/db-transaction-isolation
  • https://myjamong.tistory.com/180
  • https://d2.naver.com/helloworld/407507
728x90
저작자표시 비영리 동일조건
  • 카카오스토리
  • 트위터
  • 페이스북

'CS > DataBase' 카테고리의 다른 글

스키마(Schema)  (0) 2022.01.08
인덱스와 힌트  (0) 2022.01.04
    'CS/DataBase' 카테고리의 다른 글
    • 스키마(Schema)
    • 인덱스와 힌트
    DATABASE, OS
    DeJa
    DeJa
    Tech Blog
    댓글쓰기
    인덱스와 힌트
    다음 글
    인덱스와 힌트

    티스토리툴바