Transaction 이란, 데이터베이스의 데이터를 조작하는 작업의 단위(unit of work) 입니다. 은행에서 쓰는 송금으로 예를들면, 송금은 1. 보내는 사람의 계좌에서 돈을 빼고, 2. 받는 사람의 계좌에 돈을 추가 하는 두가지 행위가 묶인 하나의 작업입니다.
Transaction은 흔히 이론적으로 ACID
원칙을 만족/보장 해야 한다고 말합니다.
여기서 ACID
란, Atomicity(원자성)
, Consistency(일관성)
, Isolation(독립성)
, Durability(영구성)
를 뜻합니다.
각 원칙은 아래와 같은 성질을 의미합니다.
Atomicity(원자성)
만약 Transaction 중간에 어떠한 문제가 발생한다면 트랜잭션에 해당하는 어떠한 작업 내용도 수행되어서는 안되며 아무런 문제가 발생되지 않았을 경우에만 모든 작업이 수행되어야 한다.
즉, Transaction 작업이 부분적으로 성공하는 일이 없도록 보장하는 성질입니다. 송금하는 사람의 계좌에서 돈은 빠져나갔는데 받는 사람의 계좌에 돈이 들어오지 않는 일이 없도록!
Consistency(일관성)
Transaction이 완료된 다음의 상태에서도 Transaction이 일어나기 전의 상황과 동일하게 데이터의 일관성을 보장해야 한다.
즉 Transaction이 끝날 때 DB의 여러 제약 조건에 맞는 상태를 보장하는 성질입니다. 송금하는 사람의 계좌 잔고가 0보다 작아지면 안 됩니다!
Isolation(독립성)
각각의 Transaction은 서로 간섭없이 독립적으로 수행되어야 한다.
즉 Transaction이 진행되는 중간상태의 데이터를 다른 Transaction이 볼 수 없도록 보장하는 성질입니다. 송금하는 사람의 계좌에서 돈은 빠져나갔는데 받는 사람의 계좌에 돈이 아직 들어가지 않은 DB의 상황을 다른 Transaction이 읽으면 안 됩니다.
Durability(영구성)
Transaction이이 정상적으로 종료된 다음에는 영구적으로 데이터베이스에 작업의 결과가 저장되어야 한다.
Transaction이 성공했을 경우 해당 결과가 영구적으로 적용됨을 보장하는 성질입니다. 한번 송금이 성공하면 은행 시스템에 장애가 발생하더라도 송금이 성공한 상태로 복구할 수 있어야 합니다.
실제로 ACID 원칙은 종종 지켜지지 않는다. 왜냐하면, ACID 원칙을 strict 하게 지키려면 동시성이 매우 떨어지기 때문이다.
그래서 DB 엔진은 ACID 원칙을 희생하여 동시성을 얻을 수 있는 방법을 제공했습니다. 방법은 바로 Transactional Isolation Level
입니다.
참고자료 ➲ Transactional
Transaction에서 일관성 없는 데이터를 허용하도록 하는 수준을 뜻합니다.
데이터베이스는 ACID 특징과 같이 트랜잭션이 독립적인 수행을 하도록 합니다. 따라서 Locking을 통해 트랜잭션이 DB를 다루는 동안 다른 트랜잭션이 관여하지 못하도록 막는 것이 필요합니다. 하지만 무조건 Locking으로 동시에 수행되는 수많은 트랜잭션들을 순서대로 처리하는 방식으로 구현하게 되면 데이터베이스의 성능은 떨어지게 될 것입니다.
그렇다고 해서 성능을 높이기 위해 Locking의 범위를 줄인다면, 잘못된 값이 처리될 문제가 발생하게 됩니다. 따.라.서 최대한 효율적인 Locking 방법이 필요합니다.
사용자1이 A라는 데이터를 B라는 데이터로 변경하는 동안 사용자2는 아직 완료되지 않은(Uncommitted) 트랜잭션이지만 데이터B를 읽을 수 있다.
Read Committed (Level 1)
SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리는 계층
트랜잭션이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기하게 됩니다. 그리고 Commit이 이루어진 트랜잭션만 조회가 가능합니다. 대부분 SQL 서버가 Default로 사용하는 Isolation Level 입니다.
사용자 1이 A라는 데이터를 B라는 데이터로 변경하는 동안 사용자2는 해당 데이터에 접근이 불가능합니다.
Repeatable Read (Level 2)
트랜잭션이 완료될 때 까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 계층입니다.
트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장합니다. 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정은 불가능합니다! MySQL에서 Default로 사용하는 레벨입니다.
Serializable (Level 3)
트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock이 걸리는 계층
완벽한 읽기 일관성 모드를 제공합니다. 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능합니다.
Dirty Read
커밋되지 않은 수정중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상입니다.
어떤 트랜잭션에서 아직 실행이 끝나지 않은 다른 트랜잭션에 의한 변경사항을 보게되는 경우를 뜻합니다.
발생 Level: Read Uncommitted
Non-Repeatable Read
한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 일관성이 깨진 현상을 말합니다.
발생 Level: Read Committed, Read Uncommitted
Phantom Read
한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상을 말합니다.
트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타나는 현상입니다.
발생 Level: Repeatable Read, Read Committed, Read Uncommitted