CS
트랜잭션에 대하여
dhfkdlsj
2025. 1. 3. 15:12
트랜잭션(Transaction)
트랜잭션은 데이터베이스와 애플리케이션 간의 데이터 거래에서 안정성을 확보하기 위한 단일 논리적 작업 단위입니다.
예를 들어, 계좌 이체 과정에서 인출 또는 입금만 성공하면 데이터 무결성이 깨질 수 있습니다. 이를 방지하기 위해 트랜잭션을 사용합니다.
트랜잭션은 모든 작업이 성공적으로 완료되거나, 실패 시 모든 작업이 원래 상태로 되돌아가는 원자성을 보장하여 데이터의 일관성과 무결성을 유지합니다.
트랜잭션의 필요성: 계좌 이체 예시
문제 상황
- 사용자 A 계좌: 10,000 원
- 사용자 B 계좌: 5,000 원
- 사용자 A가 사용자 B에게 2,000원을 이체하는 트랜잭션이 실행됩니다.
- 이 과정에서 A 계좌에서 2,000원 인출이 성공하고, B 계좌에 2,000원 입금이 실패한다면 데이터 무결성이 깨집니다.
해결 방법
- 트랜잭션을 통해 모든 작업이 완료되거나 실패 시 전부 되돌리는 원자성을 보장하여 문제를 방지할 수 있습니다.
주요 명령어
MySQL 명령어
START TRANSACTION
: 트랜잭션 시작COMMIT
: 작업 내용을 데이터베이스에 저장하고 트랜잭션 종료ROLLBACK
: 작업(마지막 커밋 전까지)을 취소하고 이전 상태로 되돌림
Spring Framework
@Transactional
: 메서드 내의 모든 데이터베이스 작업을 하나의 트랜잭션으로 묶어 처리
ACID 속성
- Atomicity (원자성)
- 트랜잭션 내 모든 작업이 모두 성공하거나 모두 취소되어야 합니다.
- "All or Nothing"
- Consistency (일관성)
- 트랜잭션 실행 후 데이터베이스는 항상 일관성 있는 상태를 유지해야 합니다.
- 트랜잭션이 데이터베이스 규칙을 위반하면
ROLLBACK
됩니다.
- Isolation (고립성)
- 여러 트랜잭션이 동시에 실행될 때 서로의 연산에 영향을 주지 않아야 합니다.
- DBMS의 동시성 제어는 Serializability와 Recoverability를 보장합니다.
- Durability (영구성)
- 커밋된 트랜잭션의 변경 사항은 시스템 장애가 발생해도 유지됩니다.
주요 용어 정리
- R1(A): A 데이터를 읽는 작업 (Read)
- W1(A): A 데이터를 쓰는 작업 (Write)
- operation:R1(A)와 같은 작업들
- Schedule: 여러 트랜잭션이 동시에 실행될 때 연산들의 실행 순서
Schedule 유형
- Serial Schedule
- 트랜잭션이 겹치지 않고 순차적으로 실행됩니다.
- 동시성이 없으므로 성능이 떨어집니다.
- 현실적으로 사용하기 어렵습니다.
- Ex) A가 B에게 송금하는 트랜잭션과 B가 자신의 통장에 입금하는 트랜잭션의 Serial Schedule:
- R1(A) – W1(A) – R1(B) – W1(B) – C1 – R2(B) – W2(B) – C2
- Nonserial Schedule
- 트랜잭션이 겹쳐서 실행
- 동시성이 높아 같은 시간동안 더 많은 transaction을 처리할 수 있으나, 실행 순서에 따라 이상 결과가 발생할 수 있습니다.
- R1(A) – W1(A) – R1(B) – R2(B) – W2(B) – C2 – W1(B) – C1
- 위와 같은 경우 2번 트랜잭션의 결과가 사라지고 1번 트랜잭션의 결과만 남게 됩니다.
- Serial schedule 과 동일한 Nonserial schedule을 실행함으로써 Nonserial과 serial의 장점을 모두 챙길 수 있습니다.
Conflict Operations
- 서로 다른 트랜잭션이 같은 데이터에 접근하며 최소 하나는
Write
작업을 수행하는 경우를 말합니다. - R1(A) – W1(A) – R2(B) – W2(B) – C2 – R1(B) – W1(B) – C1
- 위의 경우 R2(B)와 W1(B), W2(B)와 R1(B), W2(B)와 W1(B)가 Conflict operation입니다.
Conflict Equivalent
- 두 스케줄이 같은 트랜잭션을 포함하고, Conflict Operation의 순서가 동일함을 뜻합니다.
- Ex)
- A. R1(A) – W1(A) – R2(B) – W2(B) – C2 – R1(B) – W1(B) – C1
- B. R2(B) – W2(B) – C2 – R1(A) – W1(A) – R1(B) – W1(B) – C1
- A,B Schedule은 Conflict equivalent합니다.
- B Schedule은 Serial schedule입니다.
- 이처럼 Serial schedule과 Conflict equivalent할 때 Conflict serializable하다라고 합니다.
- 고로 A Schedule은 Conflict serializable 합니다.
- R1(A) – W1(A) – R1(B) – R2(B) – W2(B) – C2 – W1(B) – C1
- 위의 경우는 어떤 Serial schedule과도 Conflict equivalent하지 않습니다.
- 이를 Not conflict serializable 이라고 합니다.
- Conflict serializable한 Nonserial schedule을 실행함으로써 Nonserial과 serial의 장점을 모두 챙길 수 있습니다.
- 어떤 schedule도 serializable하도록 만들어 주는 것이 concurrency control 이고 이것과 밀접하게 관련된 트랜잭션 속성이 Isolation입니다.
- 하지만 Isolation을 너무 엄격하게 하여 Serializability를 너무 엄격하게 추구하게되면 동시성이 떨어지기 때문에 성능이 줄게됩니다.
- 이를 개발자들이 필요에따라 유연하게 선택하게 해주는 것이 Isolation level입니다.
- 이에 대해서는 뒤에서 더 설명드리도록 하겠습니다.
Recoverability (회복 가능성)
- Unrecoverable Schedule
- 한 트랜잭션이 커밋되기 전에 다른 트랜잭션이 데이터를 읽고 커밋하는 경우
- 이때 첫 번째 트랜잭션이 롤백되면, 두 번째 트랜잭션도 영향을 받아 데이터 불일치가 발생하지만, 이미 커밋되었기 때문에 durability 속성 때문에 롤백이 불가능합니다.
- Recoverable Schedule
- 읽은 데이터를 작성한 트랜잭션이 먼저 커밋된 후 다른 트랜잭션이 커밋
- 데이터 일관성을 유지 할 수 있습니다.
- Cascading Rollback
- 여러 트랜잭션의 롤백이 연쇄적으로 일어나는 것 -> 처리 비용이 많이 듭니다.
- 데이터를 write한 트랜잭션이 commit 또는 rollback 한 뒤에 데이터를 읽거나 쓰는 schedule만 허용하자!
- 이를 cascadeless schedule이라고 합니다.
- 하지만 이 경우도 데이터를 읽지 않는 schedule은 다 허용하게 되어서 문제가 발생합니다.
- 예:
write1(A) – write2(A) – commit2(A) – rollback1(A)
을 하게 되면 결과적으로 1번과 2번 트랜잭션 모두 rollback이 되어버림. - 데이터를 write한 트랜잭션이 commit 또는 rollback 한 뒤에 데이터를 읽거나 쓰는 schedule만 허용하자!
- 이를 strict schedule이라고 합니다.
- recoverable - cascadeless - strict 순으로 범위가 좁아진다고 생각하시면 좋을 것 같습니다.
Isolation Levels (격리 수준)
이상 현상
- Dirty Read
- 커밋되지 않은 데이터를 읽음
- Non-repeatable Read
- 동일한 데이터를 여러 번 읽을 때 값이 달라짐
- Phantom Read
- 데이터가 갑자기 추가되거나 제거됨
- 이런 이상한 현상들이 모두 발생하지 않게 만들 수 있지만 그러면 제약사항이 많아져서 동시 처리 가능한 트랜잭션 수가 줄어들어 결국 DB의 전체 처리량(throughput)이 하락하게 됩니다.
- Isolation level : 일부 이상 현상은 허용하는 몇 가지 level을 만들어서 사용자가 필요에 따라서 적절하게 선택할 수 있도록 한 것입니다.
Isolation Level
Isolation Level | Dirty Read | Non-repeatable Read | Phantom Read |
---|---|---|---|
Read uncommitted | Yes | Yes | Yes |
Read committed | No | Yes | Yes |
Repeatable read | No | No | Yes |
Serializable | No | No | No |
- Serializable | |||
- 이상 현상이 전혀 발생하지 않도록 보장 | |||
- 동시성 감소로 성능 저하 가능 |
- 애플리케이션 설계자는 isolation level을 통해 전체 처리량(throughput)과 데이터 일관성 사이에서 어느 정도 거래(trade)를 할 수 있다
추가 이상 현상
- Dirty Write: 커밋되지 않은 데이터를 덮어씀
- Lost Update: 업데이트가 덮어써짐
- Read Skew
- Write Skew
- MySQL, Oracle, PostgreSQL, SQL Server 등은 표준 Isolation Level에 기반하여 정의하고 있습니다.
- 각 DBMS의 공식 문서를 참고하여 동작 방식을 이해하고 적절히 사용해야 합니다.
- concurrency control은 serializability, recoverability, 그리고 이와 관련된 isolation level을 제공합니다.
- DBMS에서 concurrency control를 구현 하는데에 기본이 되는 락과 MVCC등을 더 공부해보면 좋을 것 같습니다.