데이터베이스 - 트랜잭션, ACID, 트랜잭션 격리 수준

네민·2025년 1월 11일
0

우당탕탕 cs 공부

목록 보기
7/14

트랜잭션

데이터베이스에서 하나의 작업 단위를 의미 → 모든 작업이 한꺼번에 수행되어야함

일련의 작업들이 모두 성공하거나, 모두 실패해야 하는 연산 집합 → 모든 작업이 성공해야 반영되고, 문제가 생기면 이전 상태로 돌아감. 즉, 중간 작업까지만 반영을 하는게 아니라 모든 작업을 원상태로 복구하는 것임

예시)

A 계좌 → B 계좌로 100만 원 송금 시:

  • A 계좌 출금 성공 + B 계좌 입금 성공 ⇒ 성공 (커밋)
  • A 계좌 출금 성공 + B 계좌 입금 실패 ⇒ 롤백(되돌림)

트랜잭션 상태

  1. 활성: 트랜잭션 정상적으로 실행 중인 상태
  2. 부분 완료: 트랜잭션 마지막까지 실행, 커밋 전 상태
  3. 완료: 트랜잭션이 성공 후 종료되어 커밋하여 데이터베이스에 영구적으로 반영한 상태
  4. 실패: 트랜잭션 실행에 오류 발생해서 중단된 상태
  5. 철회: 트랜잭션이 비정상적으로 종료되어 이전 상태로 복구된 상태

트랜잭션 명령어

  1. 커밋(Commit): 모든 작업이 완료되었음을 선언, 변경 사항을 확정하는 명령어 → 데이터가 완전히 반영되어 업데이트됨
  2. 롤백(Rollback): 트랜잭션 처리 과정 중 문제가 발생해서 변경사항을 취소하는 명령어 → 트랜잭션 시작 이전 상태로 되돌림

ACID 원칙

1. 원자성 (Atomicity)

데이터베이스에 모두 반영되거나, 모두 반영되지 않아야 한다는 것

→ 하나의 작업이라도 실패하면 모든 변경사항 취소하고 롤백해야함

2. 일관성 (Consistency)

작업 처리 결과가 항상 일관성이 있어야 한다는 것

→ 트랜잭션이 진행되는 동안, DB 변경이 있더라도 처음에 참조하고 있던 DB로 읽음

3. 독립성 (Isolation)

동시에 여러 트랜잭션이 실행되더라도, 각 트랜잭션은 독립적으로 수행해야함

→ 하나의 트랜잭션이 완료될 때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없음

4. 영구성 (Durability)

트랜잭션 완료 후 시스템 장애나 오류가 생겨도 결과가 영구적으로 보존하고 반영되어야 한다는 것


트랜잭션 격리 수준 (Transaction Isolation Level)

여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 여부 결정

SERIALIZABLE

가장 엄격한 격리 수준 상태

모든 트랜잭션을 순차적으로 실행한 것처럼 동작함

읽기, 쓰기, 추가에 대해 모두 잠금을 걸어 여러 트랜잭션이 동일한 레코드에 동시접근 불가능함 → 성능 떨어짐 → 그래서 극단적으로 보안이 중요한 경우에만 써야함

데이터 무결성과 일관성 완벽 보장

REPEATABLE READ

하나의 트랜잭션 내에 동일한 데이터를 여러 번 조회해도 동일한 결과 반환

MVCC(다중 버전 동시성 제어)를 사용해서 변경 전 데이터를 Undo 영역에 저장해 변경 전후 데이터 관리

트랜잭션 번호를 참조해 커밋된 시점의 데이터 사용

새로운 레코드가 추가되는 것은 막을 수 없음 (유령 읽기) → 근데 MySQL은 갭락을 사용해서 가능함.

MVCC를 통해 한 트랜잭션 내에서 동일한 결과를 보장하지만, 새로운 레코드가 추가되는 경우에는 부정합이 일어날 수 있음.

위의 예제를 보면 확인가능한데, B 트랜잭션이 먼저 실행되고 난 후 A 트랜잭션이 민규를 망규로 변경했음. 하지만 REPEATABLE READ는 트랜잭션 번호를 참고하여 먼저 실행된 트랜잭션 데이터만을 조회하는데 B 보다 나중에 실행된 트랜잭션 데이터가 존재하기 때문에 언두 로그를 참고해서 데이터를 조회하게 됨. 이렇게 일관성을 지키며 동일한 결과를 확인할 수 있음.

하지만 새로운 레코드의 추가는 막을 수가 없음. → 유령 읽기 ⇒ 하지만 MVCC에 의해 일반적인 상황에서는 유령 읽기가 발생하지 않음. 나중에 트랜잭션이 추가한 레코드는 무시하기 때문임.

그렇다면 어떤 상황에 유령 읽기가 발생하냐?

잠금이 사용되는 경우.

B 사용자가 “SELECT FOR UPDATE = 쓰기 잠금” 로 조회를 한다.

MySQL은 갭락을 사용해서 유령읽기 막음

나머지는안막아줌 postgres같은거

갭락 → 예를 들면 50 이상에 락을 건다. 그럼 트랜잭션 종료 이전까지 쭉 락을 거는거임. 현재 테이블에서 50까지 있는데 A에서51 추가한다고 해도 락이 걸려있어서 추가 못하는 느낌

갭락 없으면 그냥 50이상에 락 거는거 현재 테이블 기준으로 걸어서 이 다음 A가 51 추가할려고 하면 추가하고 커밋됨. 그리고 B가 또 읽으면 유령읽기가 되는거임

READ COMMITTED

커밋된 데이터만 조회할 수 있음 → 하나의 트랜잭션 내에서 동일한 쿼리 반복하면 다른 트랜잭션의 커밋된 결과를 읽게 됨

더티 리드 방지 가능, 동시성 처리 성능 높음

유령읽기(Phantom Read): 새롭게 추가되거나 삭제되는거 갭락으로 막기

반복읽기불가능(Non-Repeatable Read) : 수정되는거? 레코드락으로 막기

더티 리드: 한 트랜잭션에서 커밋되지 않은 변경된 데이터를 다른 트랜잭션이 읽을 수 있는 상황 즉, 아직 확정되지 않은 데이터를 읽어와 작업을 수행함으로써 잘못된 데이터를 참조하거나 잘못된 연산 결과가 발생할 수 있음

READ UNCOMMITED

커밋되지 않은 데이터도 조회할 수 있음 → 다른 트랜잭션에서 커밋되지 않은 데이터 읽을 수 있음 ⇒ 더티 리드 발생할 수 있음

격리 수준이 낮기 때문에 트랜잭션 간 충돌이 거의 없고 빠르게 처리됨

무결성과 일관성 보장이 약함

로그 저장같은 단순 작업에 사용됨


Undo와 Redo

Undo 영역

데이터 변경 작업 전에 변경 전 데이터를 저장하는 공간

ROLLBACK 상황에 Undo 영역을 참조하여 변경 전 상태로 복구 혹은 MVCC 제공

Redo 영역

데이터 변경 작업의 변경 후 데이터를 저장하는 공간

COMMIT 되기 전 변경된 데이터를 로그 파일에 기록, 시스템 장애가 발생하더라고 복구할 수 있도록 보장


느낀점
DB는 너무 재미있고 공부할 때마다 좋은데... 설명하기 너무 어렵다.
이 글을 읽으면 이해할 사람이 있을까? 싶은데 나중에 시간이 지난 뒤 읽어보고 이상하다 싶으면 수정해야겠다. 트랜잭션 격리 수준은 참고 자료의 블로그 추천. 계속 읽다보면 이해가 됨. 예제 사진도 있어서 좋음.
그리고 InnoDB의 갭락이라던가 격리수준이 어떤지 몰랐는데 알게 돼서 좋았다


참고 자료
[MYSQL] 📚 트랜잭션(Transaction) 개념 & 사용 💯 완벽 정리
[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기

profile
기록하자

0개의 댓글