[DB] 트랜잭션
트랜잭션이란?
트랜잭션은 데이터의 상태 변화에 대한 작업 단위라고 표현할 수 있다. 하지만 SQL문 한 줄이 트랜잭션이라고 보기에는 어렵다.
은행의 송금을 예시로 드는데 A가 B에게 30,000원을 보냈다면, A의 잔고가 30,000원이 넘는 지 확인하고, 그 뒤에 A의 잔고에는 -30,000의 update가 수행되어야하며, B의 잔고에는 +30,000의 update가 수행되어야한다.
아래와 같이 START TRANSACTION;
과 COMMIT;
사이에 트랜잭션의 단위가 되는 만큼 SQL을 작성하고 SQL이 모두 성공되었다면 트랜잭션 단위 만큼의 데이터 조회, 조작 로직을 반영한다.
1
2
3
4
5
6
7
8
9
10
11
12
START TRANSACTION;
-- A의 잔액 조회
SELECT balance FROM account WHERE name = 'A';
-- A의 잔액에서 30000 차감
UPDATE account SET balance = balance - 30000 WHERE name = 'A';
-- B의 잔액에 30000 추가
UPDATE account SET balance = balance + 30000 WHERE name = 'B';
COMMIT;
트랜잭션의 단위를 얼마나 설계 잘하는가? 에 따라 서버 어플리케이션의 성능이 좌우될 수도 있다. 그리고 데이터를 얼마나 잘 다루느냐에 대해서도 많은 이점이 있다.
트랜잭션의 특징
트랜잭션의 특징은 영어의 약자로 ACID가 있다. ACID 순서대로 적어볼 것이다.
Atomicity 원자성
트랜잭션은, All or Nothing. 전부 반영이 되거나, 아니면 아예 반영이 되지 않아야한다는 특징이다. SQL문 여러 줄을 하나의 단위로 묶어서 실행하는 것인데 도중에 특정 SQL문이 문제가 생겼음에도 진행이 된다면 오류를 찾기가 어려워진다.
예를 들어, 위의 송금 과정에서 A의 계좌에 30,000원 이상이 없어 송금이 되지 않았다면 뒤의 update 문은 수행되면 안된다.
Consistency 일관성
트랜잭션의 결과는 항상 일관성이 있어야한다는 특징이다. 트랜잭션이 실행되면서 데이터베이스에 변경이 일어났더라도, 실행되기 직전 상태의 DB를 참조하여 진행한다. 이 특징으로 인해 일관성 있는 데이터를 조회할 수 있다.
Isolation 독립성
한 테이블에 두 개 이상의 트랜잭션이 동시에 실행되고 있을 경우, 어떤 하나의 트랜잭션이 다른 트랜잭션의 로직에 끼어들 수 없다는 특징이다.
Durability 영속성/지속성
트랜잭션이 성공적으로 완료되었을 경우에, 결과는 영구적으로 반영되어야한다.
트랜잭션의 연산
트랜잭션의 연산은 크게 Commit
과 Rollback
이 있다.
Commit
Commit
연산은 트랜잭션이 성공적으로 수행된 뒤에 트랜잭션 단위만큼의 데이터 상태 변화 로직의 성공을 DB에 반영하겠다는 의미의 연산이다. Commit
을 수행하면 이전 데이터가 완전히 반영되어 UPDATE된다.
1
2
3
4
5
6
7
8
9
10
11
12
START TRANSACTION;
-- A의 잔액 조회
SELECT balance FROM account WHERE name = 'A';
-- A의 잔액에서 30000 차감
UPDATE account SET balance = balance - 30000 WHERE name = 'A';
-- B의 잔액에 30000 추가
UPDATE account SET balance = balance + 30000 WHERE name = 'B';
COMMIT;
Rollback
Rollback
연산은 트랜잭션이 비정상적으로 종료되거나 데이터베이스의 일관성을 잃었을 때 트랜잭션 단위로 실행된 로직을 수행되기 전으로 되돌리는 연산을 의미한다. Rollback
연산이 수행되면 트랜잭션을 재시작하거나 폐기한다.
1
2
3
4
5
6
7
8
9
10
11
12
START TRANSACTION;
-- A의 잔액 조회
SELECT balance FROM account WHERE name = 'A';
-- A의 잔액에서 30000 차감
UPDATE account SET balance = balance - 30000 WHERE name = 'A';
-- B의 잔액에 30000 추가
UPDATE account SET balance = balance + 30000 WHERE name = 'B';
ROLLBACK;
Rollback
은 모든 연산에서 이루어지지 않는다. DDL문(CREATE, DROP, ALTER, RENAME, TRUNCATE)은 트랜잭션의Rollback
대상이 아니다.
트랜잭션의 상태
- 활성(Active) : 트랜잭션이 시작했고 동작중인 상태를 의미한다.
- 부분 완료(Partially Committed) : 트랜잭션 단위 내의 SQL문이 모두 정상적으로 동작했지만, Commit 되지 않은 상태(DB에 반영되지 않은 상태)를 의미한다.
- 완료(Committed) : 트랜잭션 작업이 모두 완료되어 DB에 반영된 상태를 의미한다.
- 실패(Failed) : 트랜잭션 작업 도중 비정상적으로 종료되어 실패한 상태를 의미한다.
- 철회(Aborted) : 트랜잭션이 실패되어 취소되고 트랜잭션 수행 전의 상태로 되돌아간(Rollback된) 상태를 의미한다.
이후에 트랜잭션의 전파, 트랜잭션 격리 수준, 그리고 @Transactional
어노테이션에 대해 다룰 계획이다.