본문 바로가기
dev/DB

Transaction & ACID

by Kyulee 2022. 10. 7.
반응형

트랜잭션 (Transaction )

데이터베이스의 상태를 변화시키기 위해 수행하는 작업 단위라고 정의할 수 있으며, 의미로는 여러 커리를 논리적으로 하나의 작업으로 묶어주는 것을 의미한다.

트랜잭션의 매커니즘

실행될 쿼리

 

대표적인 예제로 나오는 입금 출금에 대한 쿼리를 통해서 트랜잭션의 동작 과정을 살펴보려고 한다.

0. 쿼리 입력

위와 같이 쿼리문이 들어왔다고 가정하자.

1. 데이터 가져오기

쿼리문이 실행 되면 쿼리 처리기로 가고 이때 캐시를 확인하게 된다. 그러나 데이터 캐쉬는 비어있으므로 데이터가 저장된 저장소에서 데이터를 가져와 캐시 공간에 저장한다.

 

 

2. 로그에 기록하기

로그 캐시에는 2가지 형태로 나눠 있다.

ReDo 로그 : 변경 후의 값을 기록하는 로그. 트랜잭션의 시작을 저장하고, 변경되고 난 후의 값을 기록한다.

UnDo 로그 : 변경 전의 값을 기록하는 로그. 어떤 쿼리에 값의 이전 상태를 기록한다.

3. 데이터 캐시 업데이트

데이터 캐시에 저장된 값을 업데이트 한다.

상태가 변하고 난 뒤 다음 쿼리를 확인해서 있다면, 데이터 캐시에 값을 가져와서 저장한다.

4. log에 이어서 기록

 

5. 데이터 캐시 업데이트

데이터 캐시 업데이트. 이후에 쿼리문이 없다면, commit!!

 

6. Commit

이렇게 잘 동작한다면 우리는 transaction이 필요 없겠죠?

1. Rollback

우리가 commit을 하기 전에 Rollback을 해야하는 상황에서의 동작은 다음과 같다

UoDo로그를 기반을 데이터 캐시에 값이 업데이트된 것이기 때문에 맨 뒤에서부터 복구를 하면서 돌아오게 된다.

2. 예상치 못한 오류 (error)

우리가 예상치 못한 상황으로 종료되어 다시 복구하려고 하면 다음과 같은 동작한다.

ReDo 로그를 활용해서 데이터를 일관성 있도록 만들고 이를 UnDo로그를 통해서 이전상태로 돌려줄 수 있도록 한다.

이러한 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질이 존재하는데 이것이 ACID 이다.

ACID

Atomicity (원자성)

트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 한다는 의미를 담고 있으며, 이전에 보았듯이 중간에 캐시등을 통해서 바로 반영되지 않는 것을 보았을 것이다. 이처럼 완료되지 않은 트랜잭션의 중간 상태를 DB에 반영해서는 안된다.

Consistency(일관성)

트랜잭션 작업 처리 결과는 항상 일관성 있어야 한다. 테이터 베이스에 있어 제약조건이 존재한다면, 이를 위반하는 상황이 발생했을 때 트랜잭션은 종료되게 된다. 이를 통해서 데이터베이스는 항상 일관된 상태를 유지 할 수 있게 된다.

Isolation(독립성)

둘 이상의 트랜잭션이 동시 실행되고 있을 떄, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다는 성질이다.

📌 격리성(Isolation) 이슈

이는 각각의 트랜잭션이 이루어질 때 서로 간섭 없이 독립적으로 이루어질 수 있도록 격리하는데 이에 따른 문제도 발생한다.

이에 성능을 위해 손실보장이 완화되기도 한다. 이를 위해 다음과 같은 격리 수준을 나눠서 트랜잭션을 동시에 DBm를 접근하게 될 때 그 접근을 어떻게 제어할지에 대한 설정을 한다.

격리 수준

1. Read-Uncommitted

한 트랜잭션에서 커밋하지 않은 데이터를 다른 트랜잭션이 접근 가능하도록 한다. 이는 커밋하지 않은 데이터를 읽을 수 있도록 한다.

  • 이는 동시 처리 성능은 뛰어나지만 모든 격리성 이슈가 발생할 수 있다.
  • 발생 이슈 : Dirty Read, Non-Repeable Read, Phantom Read

2. Read Committed

커밋이 완료된 데이터만 읽을 수 있도록 한다. 이에 이전에 저장된 값을 읽어오게 되는데 이는 UnDo 영역에 있는 값을 읽어오게 되는 것이다.

  • Dirty Read의 발생을 방지할 수 있지만, Read Uncommitted보다 동시 처리 성능이 떨어진다.
  • DB에서는 보통 Read Committed를 기본으로 설정한다.
    • 발생 이슈 : Non-Repeable Read, Phantom Read

3. Repeatable Read

트랜잭션 마다 트랜잭션 id가 존재하는데 자신보다 낮은 트랜잭션 id를 가진 변경된 데이터만 읽어올 수 있게 된다.

  • 개별 데이터 이슈는 발생하지 않지만, 결과 집합 자체가 달아지는 Phantom Read가 발생
    • 발생 이슈 : Phantom Read

4. Serializable

  • 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근이 불가능하다. 가장 엄격한 격리 수준을 제공한다. 성능이 가장 떨어집니다.
    • 위 3가지 문제를 모두 커버

‼️ 문제점

1. Dirty Read

만약, 한 트랜잭션(T트랜잭션_1)이 데이터에 접근하여 특정 값을 수정후 커밋을 하지않아 적용이 안 된 상태에서 다른 트랜잭션(Transacion_2)이 같은 데이터를 읽는다면 어떻게 될 것인가?
트랜잭션_2 은 변경된 값으로 읽게 될 것이지만 최초의 트랜잭션(트랜잭션_1)이 커밋을 하지않고 Rollback 하거나 종료되면 문제가 생기게 된다. 트랜잭션 2은 옳지 않는 내용을 읽고 작업을 하게 되기 때문이다.

2. Non-Repeatable Read

만약, 한 트랜잭션(트랜잭션_1)이 특정 데이터를 조회하여 로직을 수행하는 와중에 다른 트랜잭션(트랜잭션_2)이 해당 데이터를 읽게 된다면, 커밋 이전에는 변경되기 전까지의 값을 읽게 되고, 커밋하면 변경된 값을 읽게 되기 때문에 동일한 로직이 커밋을 하는 전 후로 다른 결과를 낳을 수 있게 된다.

3. Phantom Read

만약, 기존에 데이터 캐시 영역에 있는 값이 아닌 새로운 값이 들어가거나 삭제 된다면, 기존에 검색에서 나왔던 값이 더 추가되거나 안보일 수 있게 된다.

Durability(지속성)

트랜잭션이 성공적으로 완료되었다면 결과를 반영하고 이는 영구적으로 지속되어야 한다. 만약 앞전에 사례를 보았을 때 모든 트랜잭션 동작이 끝나고 이에 대한 반영이 이루어진 뒤에 시스템이 다운되었다면 반영된 상태를 그대로 보존되어야 한다.

참고

트랜잭션이 보장해야 하는 ACID

[10분 테코톡] 🌼 예지니어스의 트랜잭션

반응형