트랜잭션이란?
데이터베이스의 상태를 변환시키는 하나의 논리적 작업 단위
트랜잭션의 예로는 계좌 간의 자금 이체 상황을 들 수 있다.
예시) 사용자 A가 사용자 B에게 10만 원을 송금한다.
* DB 작업
- 1. 사용자 A의 계좌에서 10만 원을 차감한다 : UPDATE 문을 사용해 사용자 A의 잔고를 변경
- 2. 사용자 B의 계좌에 10만 원을 추가한다 : UPDATE 문을 사용해 사용자 B의 잔고를 변경
* 작업 단위 : 출금(UPDATE문) + 입금(UPDATE문)
→ 이를 통틀어 하나의 트랜잭션이라고 한다.
- 위 두 쿼리문 모두 성공적으로 완료되어야만 "하나의 작업(트랜잭션)"이 완료되는 것이다. `Commit`
- 작업 단위에 속하는 쿼리 중 하나라도 실패하면 모든 쿼리문을 취소하고 이전 상태로 돌려놓아야한다. `Rollback`
데이터베이스의 상태를 변경시킨다는 것은 SELECT, UPDATE, INSERT, DELETE
와 같은 행동을 의미하며, 하나의 논리적 작업을 구성하는 일련의 연산들을 통틀어 하나의 트랜잭션이라고 한다.
트랜잭션은 다양한 데이터 항목들을 액세스하고 갱신하는 프로그램 수행의 단위가 된다.
트랜잭션을 사용하는 이유?
트랜잭션을 사용하는 이유는 데이터의 일관성을 유지하면서 안정적으로 데이터를 복구하기 위함이다.
위의 계좌 이체 예시에서 볼 수 있듯 데이터베이스에서는 데이터를 입력하거나 갱신, 삭제하는데 처리 도중 오류가 발생하면 모든 작업을 원상태로 되돌리고(Rollback), 처리 과정이 모두 성공했을 때만 최종적으로 데이터베이스에 반영한다(Commit).
트랜잭션 특징 (ACID)
Atomicity(원자성)
트랜잭션의 모든 연산들이 정상적으로 수행 완료되거나 아니면 전혀 어떠한 연산도 수행되지 않은 상태를 보장해야 한다.
- Atomicity는 쉽게 'all or nothing' 특성으로 설명된다.
Consistency(일관성)
트랜잭션의 작업 처리 결과는 항상 일관성 있어야 한다.
- 하나의 트랜잭션 이전과 이후, 데이터베이스의 상태는 이전과 같이 유효해야 한다. 다시 말해, 트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 한다는 뜻이다.
예를 들어 ‘모든 고객은 반드시 이름을 가지고 있어야 한다’는 데이터베이스의 제약이 있다고 가정한다.
다음과 같은 트랜잭션은 Consistency(일관성)를 위반한다.
1. 이름 없는 새로운 고객을 추가하는 쿼리
2. 기존 고객의 이름을 삭제하는 쿼리
데이터베이스의 유효한 상태는 다를수 있지만, 데이터의 상태에 대한 일관성은 변하지 않아야 한다. 이 예시는 ‘이름이 있어야 한다’ 라는 제약을 위반한다.
따라서 예시 트랜잭션이 일어난 이후의 데이터베이스는 일관되지 않는 상태를 가지게 된다. 이처럼 트랜잭션 수행이 보존해야 할 일관성은 기본 키, 외래 키 제약과 같은 명시적인 무결성 제약 조건들뿐만 아니라, 자금 이체 예에서 두 계좌 잔고의 합은 이체 전후가 같아야 한다는 사항과 같은 비명시적인 일관성 조건들도 있다.
Isolation(독립성)
여러 트랜잭션이 동시에 수행되더라도 각각의 트랜잭션은 다른 트랜잭션의 수행에 영향을 받지 않고 독립적으로 수행되어야 한다.
- Isolation 성질을 보장할 수 있는 가장 쉬운 방법은 모든 트랜잭션을 순차적으로 수행하는 것이다. 하지만 이 방법은 처리 속도가 느리다는 문제가 발생하게 된다.
이러한 문제를 해결하기 위해 DBMS는 격리 수준을 나누어 서비스 환경에 따라 고립 수준을 부여하도록 제공하고 있다. 트랜잭션 격리 수준은 다음과 같다.
트랜잭션 격리 수준 (Isolation Level)
1) READ UNCOMMITED
상대방에 커밋하지 않은 데이터를 읽을 수 있다. 예를 들어 사용자 A가 트랜젝션 내에서 데이터를 수정하고 있는데 사용자 B가 그 데이터를 조회할 수 있다. 커밋되지 않은 데이터를 조회하는 것을 Dirty Read라고 말한다. 사용자 B가 데이터를 사용하는 도중에 사용자A가 데이터를 롤백시켜 버리면 데이터 정합성이 깨질 수 있다.
2) READ COMMITED
상대방이 커밋한 데이터만 조회할 수 있다. 따라서 Dirty Read는 발생하지 않는다. 하지만 NON-REPEATABLE READ가 발생할 수 있다. 예를 들어 사용자A가 커밋한 데이터를 사용자B가 트랜젝션 내에서 조회하고 있는데 이후에 사용자 A가 데이터를 수정 후 다시 커밋한다면 사용자B는 같은 트랜젝션 내에서 다른 데이터를 조회하게 되는 것이다.
3) REPEATABLE READ
한번 조회한 데이터는 트랜젝션 내에서 다시 조회해도 같은 데이터가 나오는게 보장된다. 하지만 PHANTOM READ가 발생할 수 있다. 예를 들어 사용자A가 트랜젝션 내에서 20살 이하의 회원 리스트를 조회했을때, 중간에 사용자B가 회원을 20살 이하 회원을 한명 추가한다면, 다시 리스트를 조회했을때 나오는 결과가 달라질 수 있다. 이처럼 결과 집합이 달라지는 것을 PHANTOM READ라고 한다.
4) SERIALIZABLE
Serializable은 이름 그대로 트랜잭션을 순차적으로 진행시킨다.가장 엄격한 수준의 격리성이지만 동시성 처리에는 매우 약하다.
트랜 잭션 격리수준에 따라 발생할 수 있는 문제점을 정리하면 다음과 같다.
- Dirty Read : 어떠한 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상
- Non-Repetable Read: 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 "REPEATABLE READ" 정합성에 어긋나는 현상
- Phantom Read : 한 트랜잭션 내에서 동일한 쿼리를 두 번 보냈을 때, 첫 번째 쿼리에서 존재하지 않던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상
Durability(지속성)
트랜잭션이 성공적으로 완료되었으면, 결과는 영구적으로 반영되어야 한다.
- 트랜잭션이 성공적으로 완료되어 커밋되고 나면, 해당 트랜잭션에 의한 모든 변경은 향후에 어떤 소프트웨어나 하드웨어 장애가 발생되더라도 보존되어야 한다.
트랜잭션 연산
하나의 트랜잭션은 Commit 되거나 Rollback 된다.
Commit
- 모든 작업들이 정상적으로 처리되었다고 확정하는 명령어로 처리과정을 DB에 영구저장하는 것
- Commit을 수행하면 이전 데이터가 완전히 UPDATE 된다.
Rollback
- Rollback은 작업 중 문제가 발생되어 트랜잭션의 처리과정에서 발생한 변경사항을 취소하는 명령어이다.
- 트랜잭션이 시작되기 이전의 상태로 되돌린다. (즉, 마지막 커밋을 완료한 시점으로 다시 되돌아감)
트랜잭션 상태
- 활성(Active) : 트랜잭션이 정상적으로 실행중인 상태
- 실패(Failed) : 트랜잭션 실행에 오류가 발생하여 중단된 상태
- 철회(Aborted) : 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태
- 부분 완료(Partially Committed) : 트랜잭션의 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태
- 완료(Committed) : 트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태
References
https://d2.naver.com/helloworld/407507
https://coding-factory.tistory.com/226
'TIL' 카테고리의 다른 글
[TIL] SQL Injection (0) | 2024.12.16 |
---|---|
[TIL] AWS 인프라 및 서비스 개요 (1) | 2024.12.09 |
[TIL] 데이터베이스 JOIN (0) | 2024.11.25 |
[TIL] Index (3) | 2024.11.11 |
[TIL] 분산락 (3) | 2024.10.21 |