트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위이다.
사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업단위이다.
하나의 트랜잭션은 Commit되거나 Rollback된다.
예를 들어,
ATM으로 계좌이체를 한다고 생각해보면,
A 은행에서 출금하여 B은행으로 송금
송금 중, 알 수 없는 오류가 발생하여 A은행 계좌에서 돈은 빠져 나갔지만 B은행의 계좌에 입금되지 않음
이와 같은 상황을 막기위해 거래가 성공적으로 모두 끝나야 이를 완전한 거래로 승인하고, 거래 도중 뭔가 오류가 발생했을 때는 이 거래를 처음부터 없었던 거래로 완전히 되돌리는 것.
이렇게 거래의안전성을 확보하는 방법이 트랜잭션이다. 데이터베이스에선 테이블에서 데이터를 읽어 온 후 다른 테이블에 데이터를 입력하거나 갱신, 삭제하는데 처리 도중 오류가발생하면 모든 작업을 원상태로 되돌립니다. 데이터베이스에선 처리 과정이 모두 성공했을 때만 최종적으로 데이터베이스에 반영한다. 내 계좌에서 돈이 출금되는 행위 하나만 또는 상대 계좌로 돈이 입금되는 행위 하나만 실행 되서는 안되고 두가지의 행위가 하나의 업무로 같이 진행이 되야 된다. 즉, 더이상 쪼개질 수 없기에 일부만 작동해선 안된다는 것이 트랜잭션의 핵심이다.
- Commit : 모든 부분 작업이 정상적으로 완료되면 이 변경사항을 한꺼번에 DB에 저장한다.
- Rollback : 부분 작업이 실패하면 트랜잭션 실행 전으로 되돌린다. 하나의 트랜잭션 처리가 비정상적으로 종료되어 DB의 일관성을 깨뜨렸을때, 원자성을 구현하기 위해 해당 트랜잭션이 행한 모든 연산을 취소하는 행위이다. 이 때, 모든 연산을 취소하지 않고 정해진 부분까지만 되돌리고 싶을 때 사용하는 것이 Save point 이다.
- SavePoint : 일반적으로 ROLLBACK을 명시하면 INSERT, DELETE, UPDAT 등의 작업 전체가 취소되지만, SAVEPOINT를 사용하면 전체가 아닌특정 부분에서 트랜잭션을 취소시킬 수 있다. 취소하려는 지점을 SAVEPOINT로 명시한뒤 **ROLLBACK TO 세이브포인트이름;**을 실행하면 지정한 해당 SAVEPOINT 지점까지 처리한 작업이ROLLBACK된다.
활성(Active): 트랜잭션이 정상적으로 실행 중인 상태
실패(Failed) :트랜잭션 실행에 오류가 발생하여 중단된 상태
철회(Aborted) :트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태
부분 완료(Partially Committed) :트랜잭션의 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태
완료(Committed) :트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태
트랜잭션의 성질 (ACID)
Atomicity(원자성)
트랜잭션의 연산은 데이터베이스에 모두 반영되든지 아니면 전혀 반영되지 않아야 한다.
트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.
Consistency(일관성)
트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환한다.
시스템이 가지고 있는 고정요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.
Isolation(독립성,격리성)
둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수 없다.
수행중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.
Durablility(영속성,지속성)
성공적으로 완료된 트랜잭션의 결과는 시스템이 고장나더라도 영구적으로 반영되어야 한다.
격리 수준에 따라 발생하는 현상
Dirty Read : 특정 트랜잭션에 의해 데이터가 수정되었지만, 아직 커밋되지 않은 상황에서 다른 트랜잭션이 해당 변경 사항을 조회할 수 있는 문제 (ex. A의 계좌가 $100에서 $0으로 변경한 내용이 아직 커밋되지 않은 상태라도 그 이후에 B가 조회했을 때 결과가 $0으로 나온 경우 -> 수정한 트랜잭션 A가 변경 사항을 롤백하면, 그 데이터를 읽은 다른 트랜잭션 B가 더티 데이터를 가지고 있다고 말함)
Non Repeatable Read : 어떤 트랜잭션이 같은 쿼리를 2번 실행하는데 ( 그 사이에 다른 트랜잭션이 수정/삭제를 하여) 같은 쿼리에 다른 값이 나오는 경우
Phantom Read :한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우
트랜잭션 격리 수준의 종류 => 레벨 올라갈수록 격리성 강해진다. 동시성 약해진다.
READ uncommitted (LEVEL 0) => 팬텀리드, 반복 가능하지 않은 조회, 더티 리드 발생
READ committed (LEVEL 1) => 팬텀 리드, 반복 가능하지 않은 조회 발생
REPEATABLE READ (LEVEL 2) => 팬텀리드 발생
SERIALIZABLE (LEVEL 3)
➕ 트랜잭션 전파
여러 트랙잭션 관련 메서드의 호출을 하나의 트랜잭션에 묶이도록 하는 것을 말합니다.
Spring 프레임워크에서는 @Transactional annotation을 통해 여러 쿼리 관련 코드들을 트랜잭션으로 처리합니다.
Isolation Level (트랜잭션 격리 수준)
여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 여부를 결정하는 것
READ UNCOMMITTED
가장 낮은 격리 수준으로, 트랜잭션은 다른 트랜잭션에서 아직 커밋되지 않은 데이터를 읽을 수 있다.
READ COMMITTED
트랜잭션은 다른 트랜잭션에서 커밋된 데이터만 읽을 수 있다.
REPEATABLE READ
READ COMMITTED 레벨과 다르게 처음 생성된 스냅샷을 통해 일관된 읽기 결과를 보장한다.
* MySQL InnoDB의 기본 트랜잭션 고립 수준이다. 갭 락을 통해 Phantom Read까지 거의 발생하지 않고, READ COMMITTED보다는 동시 처리 성능이 뛰어나기 때문이다.
SERIALIZABLE
가장 높은 격리 수준으로, 동시성을 완전히 제한하여 트랜잭션 간에 상호작용이 없다.
즉, 모든 트랜잭션을 순차적으로 실행하는 것과 같아서 가장 높은 수준으로 데이터 일관성을 보장하지만 성능 문제가 발생할 수 있다.