✨ 트랜잭션?
트랜잭션(Transaction)은 업무 처리를 위한 논리적 작업 단위이다. 작업의 논리적 단위는 단일 연산이 아닐 수 있고, 이 말인 즉 하나의 트랜잭션이 두 개 이상의 갱신 연산으로 이루어질 수도 있다.
데이터를 일관성 있게 처리하기 위해서는 트랜잭션에 속한 두 개 이상의 갱신 연산을 동시에 실행할 수 있어야 하는데, 이것은 불가능하기 때문에 대신 여러 개의 갱신 연산이 하나의 작업처럼 전부 처리되거나, 아예 하나도 처리되지 않도록 동시 실행을 구현한다.
🪡 트랜잭션의 특징
트랜잭션은 네가지의 주요 특징을 가지고 있는데, 영문 첫 글자를 따서 'ACID' 라고 부른다.
1) 원자성(Atomicity)
트랜잭션은 더 이상 분해가 불가능한 업무의 최소 단위이기 때문에, 전부 처리되거나 아예 하나도 처리되지 않아야 한다.
2) 일관성(Consistency)
일관된 상태의 데이터베이스에서 하나의 트랜잭션을 성공적으로 완료하고 나면, 그 데이터베이스는 일관된 상태여야 한다.
즉, 트랜잭션의 실행 결과로 데이터베이스의 상태가 모순되지 않아야 한다.
3) 격리성(lsolation)
실행 중인 트랜잭션의 중간결과를 다른 트랜잭션이 접근할 수 없다.
4) 영속성(durability)
트랜잭션이 일단 그 실행을 성공적으로 완료하면, 그 결과는 데이터베이스에 영속적으로 저장된다.
🧶 트랜잭션 격리성
트랜잭션의 격리성과 일관성은 Lock을 강하게 오래 유지할수록 강화되고, Lock을 최소화할수록 약화된다.
🐣 낮은 단계의 격리성 수준에서 발생할 수 있는 현상들
1) Dirty Read
다른 트랜잭션에 의해 수정되었지만, 아직 커밋되지 않은 데이터를 읽는 것을 말한다. 변경 후 아직 커밋되지 않은 값을 읽었는데, 변경을 가한 트랜잭션이 최종적으로 롤백된다면 그 값을 읽은 트랜잭션은 비일관된 상태에 놓이게 된다.
2) Non-Repeatable Read
한 트랜잭션 내에 같은 쿼리를 두 번 수행했는데, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제하는 바람에 두 쿼리의 결과가 다르게 나타나는 현상을 말한다.
3) Phantom Read
한 트랜잭션 내에서 같은 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.
🐤 트랜잭션 격리성 수준
ANSI/ISO SQL 표준(SQL92)에서 정의한 4가지 트랜잭션 격리성 수준(Transaction lsolation Level)은 다음과 같다.
1) Read Uncommitted
트랜잭션에서 처리 중인 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용한다.
2) Read Committed
트랜잭션이 커밋되어 확정된 데이터만 다른 트랜잭션이 읽도록 허용함으로써, Dirty Read를 방지해준다. 커밋된 데이터만 읽더라도 Non-Repeatable Read와 Phantom Read 현상을 막지는 못한다.
3) Repeatable Read
트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌는 현상을 방지해준다. 이 트랜잭션 격리성 수준이 Phantom Read 현상을 막지는 못한다. 첫 번째 쿼리에서 없던 새로운 레코드가 나타날 수 있다는 것이다.
4) Serializable Read
트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌지 않음을 물론 새로운 레코드가 나타나지도 않는다.
트랜잭션 격리성 수준은 ISO에서 정한 분류 기준일 뿐이며, 모든 DBMS가 4가지 레벨을 다 지원하지는 않는다.
예를 들어, SQL Server와 DB2는 4가지 레벨을 다 지원하지만 Oracle은 Read Committed와 Serializable Read만 지원한다. (Oracle에서 Repeatable Read 를 구현하려면 for update 구문을 이용하면 된다.)