트랜잭션을 도입하는 이유나 사용법에 대해선 알고 있으나, 자세한 이해가 부족한 상태라 개념을 다지기 위해 정리하려 한다.
1. 트랜잭션이란
여러 개의 작업을 하나로 묶은 실행 유닛을 말하며,
데이터베이스 관점에서는 상태를 변화시키는 기능을 수행하기 위한 하나 이상의 쿼리를 모아 놓은 논리적 작업 단위를 말한다.
2. 트랜잭션의 ACID
원자성(Atomicity)
트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하거나 모두 실패해야 한다.
일관성(Consistency)
모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 한다.
예를 들어, 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다.
격리성(Isolation)
동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리해야 한다.
예를 들어, 동시에 같은 데이터를 수정하지 못하도록 해야 한다.
격리성은 동시성과 관련된 성능 이슈로 인해 트랜잭션 격리 수준(Isolation level)을 선택할 수 있다.
지속성(Durability)
트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되어야 한다.
중간에 시스템에 문제가 발생해도 데이터베이스 로그 등을 사용해서 성공한 트랜잭션 내용을 복구해야 한다.
3. 트랜잭션의 상태
트랜잭션은 논리적으로 4가지의 상태에 있을 수 있으며, 연산 과정 단계를 아래와 같이 정리할 수 있다.
활성(Active)
트랜잭션이 정상적으로 실행 중인 상태를 의미한다.
부분 완료(Partially Committed)
트랜잭션의 마지막까지 실행되었지만, Commit 연산이 실행되기 전의 상태를 의미한다.
실행된 트랜잭션의 데이터는 임시 상태로 저장된다.
완료(Committed)
트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태를 의미한다.
임시 상태로 저장된 데이터가 데이터베이스에 반영되고 트랜잭션은 성공적으로 종료된다.
실패(Failed)
트랜잭션 실행 중에 오류가 발생하여 중단된 상태를 의미한다.
철회(Aborted)
트랜잭션이 비정상적으로 종료되어 Rollback 연산을 실행한 상태를 의미한다.
4. 트랜잭션의 격리 수준
여러 개의 트랜잭션이 한번에 처리될 때, 특정 트랜잭션이 변경하거나 조회하고 있는 데이터에 대해 다른 트랜잭션의 조회 허용 여부를 결정하는 것을 말한다.
트랜잭션은 원자성, 일관성, 지속성을 보장한다.
문제는 격리성인데 트랜잭션 간의 격리성을 완벽하게 보장하기 위해서는 트랜잭션을 순서대로 실행해야 하지만 이는 동시성 처리 성능을 매우 떨어트린다.
이러한 문제로 ANSI 표준은 트랜잭션의 격리 수준을 4단계로 나누어 정의했다.
직렬화 가능(SERIALZABLE)
특정 트랜잭션이 사용 중인 테이블의 모든 행을 다른 트랜잭션이 접근할 수 없도록 한다.
가장 높은 데이터 정합성을 갖으나, 성능은 가장 떨어진다.
이 격리 수준에서는 단순한 SELECT 쿼리가 실행되어도, 데이터베이스 락이 걸려 다른 트랜잭션에서 해당 데이터에 접근할 수 없게 된다.
가장 엄격하지만 가장 단순한 격리 수준으로 데이터베이스에서 거의 사용되지 않는다.
반복 가능한 읽기(REPEATABLE READ)
UNDO 영역에 백업된 이전 데이터를 통해 동일한 트랜잭션 내에서 특정 행을 여러번 조회시 동일한 데이터의 응답을 보장하는 격리 수준이다.
대표적으로 MySQL InnoDB 스토리지 엔진에서 주로 사용하는 격리 수준으로 SERIALZABLE과 다르게 행이 추가되는 것을 막지 않는다.
이로 인해 PHANTOM READ 현상이 발생할 수 있다.
커밋된 읽기(READ COMMITTED)
Commit 연산이 실행 완료된 트랜잭션의 변경 사항만 다른 트랜잭션에서 조회할 수 있도록 허용하는 격리 수준이다.
특정 트랜잭션이 실행되는 동안 다른 트랜잭션은 해당 데이터에 접근할 수 없다.
가장 많이 사용되는 격리 수준으로 OracleDB 등에서 기본값으로 설정되어 있다.
하지만 특정 트랜잭션에서 데이터의 변경이 일어났지만, Commit 연산이 실행되기 전 상태라면 다른 트랜잭션에서는 변경되기 전 데이터를 응답 받게 된다.
이로 인해 NON-REPEATABLE READ 현상과 PHANTOM READ 현상이 발생할 수 있지만,
DIRTY READ 현상은 발생하지 않는다.
커밋되지 않은 읽기(READ UNCOMMITTED)
트랜잭션의 Commit 또는 Rollback 여부와 상관 없이 다른 트랜잭션에서 조회할 수 있도록 허용하는 격리 수준이다.
성능은 가장 빠르지만 데이터 정합성에 심각한 문제가 발생할 수 있고 일관성 없는 데이터의 응답 결과를 도출하게 되어 사용이 권장되지 않는다.
이로 인해 DIRTY READ 현상과 NON-REPEATABLE READ 현상, PHANTOM READ 현상이 발생할 수 있다.
정리
밑으로 갈 수록 격리 수준이 낮아지며, 동시 처리 성능은 높아진다.
반면 위로 갈 수록 격리 수준이 높아지며, 동시 처리 성능은 낮아지지만 데이터 부정합성 문제가 발생할 확률이 줄어든다.
즉, 데이터 정합성과 성능은 반비례한다.
5. 격리 수준에 따른 문제점
더티 리드(DIRTY READ)
특정 트랜잭션에 의해 데이터가 변경되었지만, Commit 연산이 실행되기 전 상태에서 다른 트랜잭션이 해당 변경 사항을 조회할 수 있는 문제를 말한다.
이는 트랜잭션 A가 데이터를 수정하고 Commit 연산을 실행하지 않은 시점에서 트랜잭션 B가 수정된 데이터를 조회할 수 있다.
트랜잭션 A가 Commit 연산을 실행하지 않고 Rollback 연산을 실행하면 데이터 정합성에 심각한 문제가 발생할 수 있다.
반복 불가능한 읽기(NON-REPEATABLE READ)
동일한 트랜잭션 내에서 같은 데이터를 여러번 조회했을 때 읽어온 데이터가 다른 문제를 말한다.
이는 트랜잭션 A가 회원 A를 조회 중인데 갑자기 트랜잭션 B가 회원 A를 수정하고 Commit 연산을 실행하면 트랜잭션 A가 다시 회원 A를 조회했을 때 수정된 데이터가 조회된다. 이처럼 반복해서 같은 데이터를 읽을 수 없는 상태를 의미한다.
팬텀 리드(PHANTOM READ)
NON-REPEATABLE READ 현상의 한 종류로 조회해온 결과의 행이 새로 생기거나 없어지는 문제를 말한다.
이는 트랜잭션 A가 10살 이하의 회원을 조회했는데 트랜잭션 B가 5살 회원을 추가하고 Commit 연산을 실행하면 트랜잭션 A가 다시 10살 이하의 회원을 조회했을 때 회원 하나가 추가된 상태로 조회된다. 이처럼 반복 조회시 결과 집합이 달라지는 상태를 의미한다.
6. 데이터베이스의 기본 격리 수준
OrableDB, TiberoDB, PostgreSQL, SybaseDB
READ COMMITTED
MariaDB, MySQL
REPEATABLE READ
Reference.
'Database' 카테고리의 다른 글
[Database] 3. DB락 개념 이해 (0) | 2024.06.04 |
---|---|
[Database] 2. 데이터베이스 연결 구조와 DB 세션 (0) | 2024.04.18 |
[Database] Oracle / MySQL의 특징과 차이 (0) | 2022.07.22 |
[Database] 데이터베이스 RDBMS / NOSQL 에 관하여 (0) | 2022.07.21 |
[MySql] Select 하여 Insert 하기 (0) | 2021.09.11 |