아리아 날다

[DB]트랜잭션과 트랜잭션 격리레벨 본문

IT인프라/데이터베이스

[DB]트랜잭션과 트랜잭션 격리레벨

Aria Park 2022. 8. 14. 23:44

DB Transaction

1. 트랜잭션이란?

트랜잭션이란(Transaction)은 더 이상 나눌 수 없는 가장 작은 하나의 단위로 데이터베이스에서는 트랜잭션을 조작함을써 사용자가 데이터베이스에 대한 완전성을 신뢰할 수 있도록 하고 있습니다. 모든 데이터베이스는 자체적으로 트랜잭션을 지원하는데, 하나의 명령을 실행했을 때 데이터베이스가 온전히 그 명령을 실행해주는 것을 의미합니다. 

 

다시말해서 트랜잭션은 데이터베이스 내에서 한꺼번에 수행되어야 하는 연산들을 말하고, 전부 성공하거나 전부 실패되거나 하는 둘 중 하나의 작업만을 수행합니다.


1. A가 B에게 1,000원을 입금하려고 한다.

2. A의 계좌에서 1,000원을 차감할 수 있는 잔액이 있는지 확인하고 B에게 1,000원을 송금한다.

3. B의 계좌는 1,000원이 증가되고 A의 계좌는 1,000원이 감소된 상태로 변경된다.


위 과정은 절대로 분리되면 안되고 일부의 작업만 진행되어서도 안됩니다. 이는 트랜잭션의 가장 기본적인 성질인 원자성(Atomicity)입니다. 만약 일부의 과정만 성공했다면 이 전체의 과정을 없던 일로 되돌려야 하고 이를 롤백(Rollback)이라고 하며, 전체의 과정을 성공했다면 수정된 내용을 데이터베이스에 반영해야 하는데 이를 커밋(Commit)이라고 합니다. 롤백이나 커밋의 과정이 실행되어야 트랜잭션이 종료됩니다.

 

1. 활동: 트랜잭션이 실행 중에 있는 상태(연산들이 정상적으로 실행 중)

2. 실패: 트랜잭션이 실행에 오류가 발생되어 중단된 상태

3. 철회: 트랜잭션이 비정상적으로 종료되어 롤백 연산을 수행한 상태

4. 부분적 완료: 커밋 연산이 실행되기 직전의 상태로 아직 변경된 것들이 저장되지 않은 상태

5. 완료: 트랜잭션이 성공적으로 종료되어 커밋 연산을 실행한 상태

 

2. 트랜잭션의 특징

1. 원자성(Atomicity)

트랜잭션은 데이터베이스에 모두 반영되거나, 전혀 반영되지 않아야 합니다. 다시 말해 완료되지 않은 트랜잭션의 중간 상태를 DB에 반영해서는 안됩니다. 이체 과정 중에 트랜잭션이 실패하게 되어 예금이 사라지는 경우가 발생하면 안되기 때문에 DBMS에는 완료되지 않은 트랜잭션의 중간 상태를 반영할 수 없습니다. 원자성은 쉽게 'all or nothing'으로 설명됩니다.

 

2. 일관성(Consistency)

트랜잭션은 DB내의 계층 관계(상태), 컬럼의 속성 등이 항상 일관되게 유지되어야 합니다. 어떠한 컬럼의 속성이 수정되었다면 trigger를 통해 일괄적으로 모든 데이터베이스에 적용해야 합니다. 예를 들어 마이너스 통장을 허락하지 않는다는 조건이 있을 때 이 조건이 위배되면 해당 트랜잭션은 종료됩니다.

 

3. 독립성(Isolation)

트랜잭션 수행 시 다른 트랜잭션이 작업에 끼어들 수 없고 독립적으로 실행되어야 합니다. 하지만 데이터베이스에 작업이 들어왔을 때 모든 작업의 독립성을 보장해 하나씩 순차적으로 진행되게 한다면 CPU는 DBMS보다 인풋 아웃풋 작업을 빈번히 수행하기 때문에 트랜잭션을 순차적으로 수행하면 CPU는 점점 응답을 기다리는 시간이 길어져 프로그램이 비효율적으로 동작하는 문제가 발생할 수 있습니다. 따라서 데이터베이스에 저장된 데이터의 무결성과 동시성의 성능을 지키기 위해 트랜잭션 설정이 중요합니다.

 

4. 지속성(Durability)

트랜잭션이 성공적으로 수행되어 커밋 되었다면 해당 트랜잭션에 의해 변경된 모든 내용은 향후에 어떤 소프트웨어나 하드웨어 장애가 발생하더라도 보존되어야 합니다. 모든 트랜잭션은 로그로 남겨져 어떤 장애에도 대비할 수 있도록 합니다.


위와 같은 트랜잭션의 성질(ACID)은 트랜잭션이 이론적으로 보장해야 하는 성질이고 실제로는 성능을 위해 손실보장이 완화되기도 합니다. 예를 들어 동일 데이터에 100개의 연결이 접근했을 때 독립성을 보장하려고 하면 순차적으로 해결해야 하기 때문에 동시성이 떨어지는 문제가 생깁니다. 이때 동시성을 얻기 위해 트랜잭션의 격리레벨을 설정할 수 있습니다.

 

3. 트랜잭션 격리 레벨 

동시에 DB에 접근할 때 그 접근을 어떻게 제어할지에 대한 설정을 말합니다. 

 

  • READ UNCOMMITED

      - 한 트랜잭션이 아직 커밋되지 않은 상태임에도 불구하고 변경된 값을 다른 트랜잭션에서 읽는 것을 허용합니다.

      - 두 개의 트랜잭션 A, B에서  A의 커밋되지 않은 트랜잭션을 B가 조회하려고 할 때, A가 커밋하지 않고 롤백하면

        B는 무효가 된 데이터 값을 읽고 처리하게 됩니다. 이를 더티 리드(Dirty Read)라고 합니다.

 

  • READ COMMITED

      - 커밋이 완료된 트랜잭션의 변경사항만 다른 트랜잭션에서 조회가 가능합니다.

      - 트랜잭션이 이루어지는 동안 다른 사용자는 해당 데이터에 접근이 불가능합니다.

      - 커밋을 하지 않으면 커밋 전의 내용을 읽어오고 커밋 후에는 변경된 데이터를 읽어오기 때문에

        이 때 데이터 불일치 문제(Non-Repeatable Read)가 발생합니다. 

 

  • REPEATABLE READ

      - 커밋이 완료된 데이터만 읽을 수 있지만 한 트랜잭션이 조회한 데이터는 트랜잭션이 종료될 때까지

        다른 트랜잭션이 변경하거나 삭제하는 것을 막습니다. (트랜잭션 범위 내에서 조회한 내용이 항상 동일성을 보장)

      - Non-Reapeatable Read의 한 종류인 Phantom Read현상(새로 생기거나 없어질 수 있음)이 발생합니다.

 

  • SERIALIZABLE

      - 한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근할 수 없습니다.

        (단순 SELECT만으로도 트랜잭션이 커밋 될 때까지 모든 데이터에 잠금(Lock)이 설정)

      - 트랜잭션의 ACID성질이 엄격하게 지켜지나 성능은 가장 떨어집니다. 

 

4. 트랜잭션 전파 타입

트랜잭션이 시작하거나 참여하는 방법에 관한 설정으로 

트랜잭션이 처리되는 과정 안에서 또 다른 트랜잭션이 처리되는 경우가 있는데, 이때 부모 트랜잭션의 유무에 따라 타입별로 트랜잭션의 경계를 설정할 수 있습니다.

 

이처럼 스프링 트랜잭션은 여러 격리 레벨과 전파 타입을 제공합니다. 중요한 데이터의 안정성에 관한 설정이기 때문에 케이스에 따라 문제가 발생하지 않도록 각 속성을 이해하고 선택해야 합니다.

Comments