트랜잭션이란 데이터베이스의 하나의 논리적인 작업 단위로, 여러 SQL문장이 하나의 단위로 묶여 모두 성공하거나 모두 실패해야 한다.
START TRANSACTION;
UPDATE account
SET balance = balance - 100
WHERE id = 1;
UPDATE account
SET balance = balance + 100
WHERE id = 2;
COMMIT;
위와 같은 이체 작업은 두 쿼리가 모두 성공해야 의미가 있으며, 하나라도 실패하면 전체를 ROLLBACK해야 한다.
트랜잭션은 모든 작업이 전부 수행되거나, 전혀 수행되지 않아야 한다.
START TRANSACTION;
UPDATE account
SET balance = balance - 100
WHERE id = 1;
UPDATE account
SET balance = balance + 100
WHERE id = 2;
COMMIT;
여기서 한 줄이라도 실패하면 ROLLBACK해야 원자성이 보장된다.
트랜잭션 전후에 데이터는 항상 일관된 상태여야 한다.
은행에서 A가 B에게 이체를 한다면 전체 계좌의 총합은 변하지 않아야 한다.
데이터의 무결성과 제약조건이 항상 유지되어야 일관성이 유지된다.
동시에 실행되는 트랜잭션이 서로 간섭하지 않아야 한다.
트랜잭션이 성공적으로 끝나면 그 결과는 영구적으로 저장되어야 한다.
COMMIT된 이루에는 시스템 장애가 나더라도 데이터는 유지되어야 한다.어떤 계좌에서 돈을 이체하고 COMMIT 된 직후 전원이 꺼지더라도,
그 이체는 반영된 상태로 남아있어야 한다.
START TRANSACTION; -- 트랜잭션 시작
COMMIT; -- 트랜잭션 성공으로 변경 내용을 영구 반영한다.
ROLLBACK; -- 트랜잭션 실패로 변경 내용을 모두 취소한다.
BEGIN도 START TRANSACTION과 동일하게 사용된다.격리 수준은 동시 실행되는 트랜잭션들이 서로 간섭하지 않도록 하기 위한 설정이다. 4가지 표준 격리 수준이 있으며, 낮은 수준일수록 성능은 좋지만 일관성 문제가 발생할 수 있다.
| 수준 | 설명 | 허용되는 이상 현상 |
|---|---|---|
| READ UNCOMMITTED | 다른 트랜잭션이 커밋하지 않은 데이터도 읽음 | Dirty Read, Non-repeatable Read, Phantom Read |
| READ COMMITTED | 커밋된 데이터만 읽을 수 있음 | Non-repeatable Read, Phantom Read |
| REPEATABLE READ | 트랜잭션 동안 읽은 값은 항상 동일 | Phantom Read |
| SERIALIZABLE | 모든 트랜잭션을 순차적으로 실행 (가장 안전, 가장 느림) | 없음 |
| 이상 현상 | 설명 |
|---|---|
| Dirty Read | 커밋되지 않은 데이터를 읽음 |
| Non-repeatable Read | 같은 SELECT를 했는데 결과가 바뀜 |
| Phantom Read | 조건에 맞는 행의 개수가 바뀌는 현상 (ex. SELECT COUNT(*)가 다르게 나옴) |
MySQL 기준의 예지이다.
-- 전역 설정 (MySQL 재시작 전까지 유지한다)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 세션 설정 (현재 연결에만 적용)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
ROLLBACK처리 해야한다.