Transaction

트랜잭션 - 데이터베이스의 DML, 즉 삽입, 갱신, 삭제와 관련된 논리적인 작업

Posted by Seohyun Park, Aileen on December 06, 2023 · 11 mins read
DATABASE

Transaction ( 트랜잭션 )

트랜잭션이란, 데이터베이스의 DML, 즉 삽입, 갱신, 삭제와 관련된 논리적인 작업을 말한다.


트랜잭션의 특징 ( ACID )

트랜잭션은 ACID 라는 특징을 가지고 있다.

1. 원자성 ( Atomicity )

트랜잭션의 처리가 완전히 끝나지 않았을 경우에는, 전혀 이루어지지 않은 것과 같아야 한다. ( All or Nothing )

2. 일관성 ( Consistency )

트랜잭션의 실행이 성공적으로 완료되면, 데이터베이스는 모순 없이 일관성이 보존된 상태여야 한다.

3. 고립성 ( Isolation )

어떤 트랜잭션도 다른 트랜잭션의 부분적 실행 결과를 볼 수 없다.

트랜잭션을 점유하고 있는 동안에는 Lock 을 걸어서, 다른 트랜잭션이 접근하지 못하도록 해야 한다.

4. 지속성 ( Durability )

트랜잭션이 성공하면, 트랜잭션의 결과를 영구적으로 보장해야 한다.

acid

트랜잭션의 상태

  1. 실행 ( Active ) : 트랜잭션이 실행 중인 상태

  2. 부분 완료 ( Partially Committed ) : 트랜잭션이 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태

  3. 완료 ( Committed ) : 트랜잭션이 성공적으로 종료된 상태

  4. 실패 ( Failed ) : 트랜잭션 실행에 오류가 발생하여 중단된 상태

  5. 철회 ( Aborted ) : 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태


동시성 제어

동시성 제어는, 동시에 실행되는 여러 개의 트랜잭션이 작업을 성공적으로 마칠 수 있도록 지원합니다.

동시성 제어 기법

  1. 락킹 ( Locking ) : 트랜잭션이 데이터를 접근하는 동안, 다른 트랜잭션이 접근하지 못하도록 Lock 을 걸어서 제어하는 방법

  2. 타임스탬프 ( Timestamping ) : 트랜잭션마다 고유한 타임스탬프를 부여하여, 트랜잭션의 실행 순서를 결정하는 방법

  3. 적합성 ( Validation ) : 먼저 트랜잭션을 수행하고, 트랜잭션을 종료할 때, 적합성을 검증하여, 트랜잭션을 종료할지, Rollback 할지 결정하는 방법

데이터베이스 시스템은 트랜잭션 직렬화 ( Serializability ) 를 보장하는, 동시성 제어를 통해 트랜잭션을 정상적으로 수행합니다.

동시성 제어 실패로 인한 대표적인 오류 현상에는, 갱신 손실, 불일치 현상, 연쇄 복귀 등이 있습니다.

갱신 손실 ( Lost Update )

두 개의 트랜잭션이 같은 데이터를 갱신할 때, 마지막에 갱신한 트랜잭션이 수행한 갱신 결과만 반영되고, 처음에 갱신한 트랜잭션이 수행한 갱신 결과는 손실되는 현상을 말합니다.

불일치 현상 ( Inconsistent Retrievals )

두 개의 트랜잭션이 같은 데이터를 조회할 때, 첫 번째 트랜잭션이 조회한 데이터와 두 번째 트랜잭션이 조회한 데이터가 일치하지 않는 현상을 말합니다.

연쇄 복귀 ( Cascading Rollback )

트랜잭션 T1 이 트랜잭션 T2 에 의해 갱신된 데이터를 읽고, 트랜잭션 T1 이 Rollback 되면, 트랜잭션 T2 도 Rollback 되는 현상을 말합니다.


락 ( Lock )

갱신 손실 문제를 해결하려면, 상대방 트랜잭션이 데이터를 사용하는지를 알 수 있는 규칙이 필요하다. 즉, 자신이 데이터를 수정중이라는 사실을 알리면 된다.

알리는 방법으로 락 ( Lock ) 이라는, 잠금장치를 사용한다.

락의 종류

  1. 공유 락 ( Shared Lock ) : 데이터를 읽을 때 사용하는 락

  2. 배타 락 ( Exclusive Lock ) : 데이터를 갱신할 때 사용하는 락

2단계 락 프로토콜 ( Two-Phase Locking Protocol )

트랜잭션은 락을 두 단계에 걸쳐서 사용한다.

  1. 확장 단계 ( Growing Phase, expanding phase ) : 트랜잭션은 필요한 락을 획득하는 단계로, 이 단계에서는 이미 획득한 락을 해제하지 않는다.

  2. 축소 단계 ( Shrinking Phase ) : 트랜잭션이 락을 해제하는 단계로, 이 단계에서는 새로운 락을 획득하지 않는다.

데드락 ( Deadlock )

2단계 락킹 기법을 사용하면, 데이터의 일관성을 유지할 수 있다. 하지만, 두 개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고, 상대방 데이터에 대하여, 락을 요청하면, 무한 대기 상태에 빠질 수 있다. 이러한 현상을 데드락 ( Deadlock ) 혹은 교착상태라고 한다.

데드락의 처리

데드락을 처리하는 방법에는, 타임아웃 ( Timeout ) 과 롤백 ( Rollback ) 이 있다.

  1. 타임아웃 ( Timeout ) : 트랜잭션이 일정 시간동안 락을 획득하지 못하면, 트랜잭션을 강제 종료시키는 방법

  2. 롤백 ( Rollback ) : 중지된 트랜잭션에서 변경한 데이터를 원래 상태로 되돌리는 방법

데드락은 대기 그래프 ( Wait-for-graph ) 를 통해 발견할 수 있다.


트랜잭션 고립 수준

앞서 설명한 락은, 트랜잭션의 동시성을 제어하는 방법이다.

하지만, 락을 사용하면, 트랜잭션의 동시성은 제어할 수 있지만, 트랜잭션의 동시성이 높아질수록, 락 경합이 심해져서, 트랜잭션의 처리 성능이 떨어지게 된다.

이러한 문제를 해결하기 위해, 트랜잭션 격리 수준 ( Transaction Isolation Level ) 을 사용한다.


MySQL InnoDB의 기본 트랜잭션 고립 수준 : REPEATABLE READ

MySQL InnoDB의 기본 트랜잭션 고립 수준은 REPEATABLE READ 이다.

InnoDB는 이 고립 수준을 사용하여 트랜잭션 중 발생할 수 있는 일관성 없는 읽기 문제를 최소화한다.


트랜잭션 고립 수준 ( Transaction Isolation Level ) 명령어 종류


1. READ UNCOMMITTED ( Level 0 ) : 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있다.

1
2
3
4
5
6
7
| 모드       | READ UNCOMMITTED                                          |
|------------|-----------------------------------------------------------|
| LOCK       | SELECT 문 - 공유락 X                                      |
|            | UPDATE 문 - 배타락 O                                      |
|            | 다른 트랜잭션의 공유락과 베타락이 걸린 테이블을 읽음       |
| SQL 문     | SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED          |
| 문제점     | 오손 읽기, 반복불가능 읽기, 유령데이터 읽기               |


2. READ COMMITTED : 트랜잭션이 커밋된 데이터만 읽을 수 있다.

1
2
3
4
5
6
7
8
| 모드       | READ COMMITTED                                            |
|------------|-----------------------------------------------------------|
| LOCK       | SELECT 문 - 공유락 X                                      |
|            | UPDATE 문 - 배타락 O                                      |
|            | 다른 트랜잭션의 공유락은 읽지만, 배타락은 읽지 못함       |
| SQL 문     | SET TRANSACTION ISOLATION LEVEL READ COMMITTED            |
| 문제점     | 반복불가능 읽기, 유령데이터 읽기                           |


3. REPEATABLE READ : 트랜잭션이 커밋된 데이터만 읽을 수 있고, 트랜잭션이 완료될 때까지 같은 데이터를 읽을 수 있다.

1
2
3
4
5
6
7
| 모드       | REPEATABLE READ                                           |
|------------|-----------------------------------------------------------|
| LOCK       | SELECT 문 - 공유락을 걸고 트랜잭션 끝까지 유지                 |
|            | UPDATE 문 - 배타락 O                                      |
|            | 다른 트랜잭션의 공유락은 읽지만, 배타락은 읽지 못함       |
| SQL 문     | SET TRANSACTION ISOLATION LEVEL REPEATABLE READ           |
| 문제점     | 유령데이터 읽기                                           |


4. SERIALIZABLE : 트랜잭션이 완료될 때까지 같은 데이터를 읽을 수 있고, 다른 트랜잭션이 같은 데이터에 대한 갱신을 할 수 없다.

1
2
3
4
5
6
7
8
| 모드       | SERIALIZABLE                                              |
|------------|-----------------------------------------------------------|
| LOCK       | SELECT 문 - 공유락을 걸고 끝나면, 바로 해지                 |
|            | UPDATE 문 - 배타락 O                                      |
|            | 다른 트랜잭션의 공유락은 읽지만, 배타락은 읽지 못함       |
|            | 인덱스에 공유락을 설정하여, 다른 트랜잭션의 INSERT 를 막음 |
| SQL 문     | SET TRANSACTION ISOLATION LEVEL SERIALIZABLE              |
| 문제점     | 없음                                                    |
1
2
3
4
5
6
| | 오손 읽기 | 반복불가능 읽기 | 유령데이터 읽기 |
|---|:---:|:---:|:---:|
| READ UNCOMMITTED | 예 | 예 | 예 |
| READ COMMITTED | 아니오 | 예 | 예 |
| REPEATABLE READ | 아니오 | 아니오 | 예 |
| SERIALIZABLE | 아니오 | 아니오 | 아니오 |


  • 오손 읽기 ( Dirty Read ) : 다른 트랜잭션이 COMMIT 하지 않은 데이터를 읽은 후, 다른 트랜잭션이 철회 (ROLLBACK) 하면서, 읽은 데이터가 취소되는 현상

  • 반복불가능 읽기 ( Non-Repeatable Read ) : 트랜잭션이 같은 데이터를 다시 읽을 때, 다른 트랜잭션이 해당 데이터를 갱신하여, 다른 값을 읽는 현상

  • 유령데이터 읽기 ( Phantom Read ) : 트랜잭션이 같은 데이터를 다시 읽을 때, 다른 트랜잭션이 해당 데이터를 삽입하여, 데이터가 존재하는 것처럼 읽는 현상


회복 ( Recovery )

회복 ( Recovery ) 은, 트랜잭션의 성공적인 종료를 보장하기 위해, 트랜잭션이 비정상적으로 종료되었을 때, 데이터베이스를 일관된 상태로 되돌리는 작업을 말한다.

로그 파일을 이용한 회복 기법

  1. Undo 기법 : 트랜잭션이 비정상적으로 종료되면, 트랜잭션이 갱신한 데이터를 이전 값으로 복원하는 방법

  2. Redo 기법 : 트랜잭션이 비정상적으로 종료되면, 트랜잭션이 갱신한 데이터를 다시 적용하는 방법

회복을 위한 로그 기록 방법

  1. 즉시 갱신 ( Immediate Update ) : 트랜잭션이 갱신한 데이터를 바로 데이터베이스에 반영하는 방법

  2. 지연 갱신 ( Deferred Update ) : 트랜잭션이 갱신한 데이터를 트랜잭션이 커밋될 때까지 임시 영역에 보관하고, 트랜잭션이 커밋되면, 임시 영역에 보관된 데이터를 데이터베이스에 반영하는 방법

체크포인트 ( Checkpoint )

데이터베이스와 트랜잭션 로그 파일을 동기화한 후, 동기화한 시점을 로그 파일에 기록해 두는데 이를 체크포인트라고 한다.


DB 세션 ( DB Session )

데이터베이스와 클라이언트(사용자 또는 애플리케이션) 간의 상호작용 기간을 말한다. 이 세션은 클라이언트가 데이터베이스에 연결을 시작할 때 생성되고, 연결을 종료할 때 종료된다. DB 세션 동안에는 여러 데이터베이스 작업들이 수행될 수 있으며, 이러한 작업들은 세션의 컨텍스트 안에서 관리된다.


Commit, Rollback, 그리고 Auto Commit 설정은 데이터베이스 트랜잭션 관리의 핵심 개념들이다. 이들은 데이터베이스에서 데이터의 일관성과 무결성을 유지하는 데 중요한 역할을 한다.

커밋 ( Commit )

데이터베이스 트랜잭션이 성공적으로 완료되었음을 나타내며, 트랜잭션 동안 수행된 모든 변경사항을 데이터베이스에 영구적으로 반영한다.


롤백 ( Rollback )

트랜잭션 동안 발생한 모든 변경사항을 취소하고, 데이터베이스를 트랜잭션 시작 시점의 상태로 되돌린다.


오토 커밋 ( Auto Commit )

데이터베이스 시스템이 각각의 데이터베이스 명령문(예: SQL 쿼리)이 실행된 직후 자동으로 commit을 수행하는 것을 말한다.

일반적으로 데이터베이스 시스템은 Auto Commit 모드가 기본적으로 설정되어있다.

이 모드에서는 사용자가 명시적으로 commit이나 rollback을 호출하지 않아도 각 SQL 명령문이 개별적인 트랜잭션으로 실행되며, SQL 명령문이 성공적으로 완료되면 commit이 자동으로 수행된다.