트랜잭션이란 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위라고 할 수 있으며, 트랜잭션에는 여러 개의 연산이 수행될 수 있다.
하나의 트랜잭션은 Commit 되거나 Rollback 된다.
트랜잭션은 하나의 논리적인 작업의 단위이기 때문에, 여러 개의 작업을 하나의 논리적인 단위로 묶어서 반영과 복구를 조정할 수 있기 위해 사용한다. 따라서, 데이터의 부정합이 일어났을 경우 롤백을 하여 데이터의 부정합을 방지할 수 있다.
Ex. A 계좌에서 출금 -> B 계좌로 입금하는 것을 하나의 논리적인 작업의 단위로 묶어서 반영과 복구를 조정할 수 있다.
트랜잭션은 4가지의 특징을 가진다. 이를 앞글자만 따서 ACID라고 부른다.
트랜잭션에는 일단적으로 접근 레벨이 있으며 DB에 따라 설정이 가능하다. 이런 격리성은 강하게 처리할 수 있으며 반대로 약하게 처리할 수도 있다.
일반적으로 Dirty Read, Non-Repeatable Read, Phantom Read 3가지이다.
Dirty Read는 다른 트랜잭션에 의해 수정됐지만 아직 커밋되지 않은 데이터를 읽는 것을 말한다. 아래의 이미지를 보면 Transaction_1이 정상처리되지 않고, Rollback 될 수 있다. 이럴 경우 그 값을 이미 읽은 Transaction_2는 잘못된 값을 가지고 본인의 로직을 처리하는 상태에 놓이게 된다.
Non-Repeatable Read는 한 트랜잭션 내에서 같은 Key를 가진 Row를 두 번 읽었는데 그 사이에 값이 변경되거나 삭제되어 결과가 다르게 나타나는 현상이다.
한 트랜잭션 내에서 같은 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.
※ Phantom Read와 Non-Repeatable Read와의 차이점은 Non-Repeatable Read는 1개의 Row의 데이터의 값이 변경되는 것이며 Phantom Read는 여러 건을 요청하는 것에 대해서 데이터의 값이 변동되는 것이다.
아래 4개의 격리수준은 ANSI/ISO SQL 표준(SQL92)에서 정의한 내용이다.
위에서 아래로 갈수록 격리 수준이 높아진다.
- 가장 낮은 격리 수준으로, 트랜잭션에서 변경된 내용이 커밋되지 않더라도 다른 트랜잭션에서 읽을 수 있다.
- 이로 인해 'Dirty Read', 'Non-Repeatable Read', 'Phantom Read'와 같은 이상현상이 발생할 수 있다.
- 데이터 정합성이 보장되지 않고, 동시성이 가장 높다.
- 이 격리 수준에서는 트랜잭션이 커밋된 데이터만 다른 트랜잭션에서 읽을 수 있다.
- 'Dirty Read'는 방지할 수 있지만, 'Non-Repeatable Read'와 'Phantom Read'는 여전히 발생할 수 있다.
- 동시성이 Read Uncommitted보다는 낮아지지만 여전히 높다.
- 이 격리 수준에서는 트랜잭션 내에서 같은 쿼리를 실행하면 항상 동일한 결과가 나온다.
- 따라서 'Non-Repeatable Read'는 방지할 수 있지만 여전히 'Phantom Read'는 발생할 수 있다.
- 동시성이 Read Committed보다는 낮아지지만 여전히 중간 정도 수준이다.
- 가장 높은 격리 수준으로, 모든 트랜잭션들이 직렬화되어 실행된다.
- 따라서 'Dirty Read', 'Non-Repeatable Read', 'Phantom Read' 모두 발생하지 않는다.
- 하지만 동시성이 가장 낮아진다. 동시에 여러 트랜잭션이 실행될 때 순차적으로 실행되어야 하므로, 성능이 저하될 수 있다.
A. Read Committed, Repeatable Read, Serializable 세 가지로 가능하다.
- Read Committed :
Read Committed 격리 수준에서는 트랜잭션에서 변경된 내용이 커밋된 데이터만 다른 트랜잭션에서 읽을 수 있기 때문에 다른 트랜잭션이 아직 커밋되지 않은 변경 사항을 읽을 수 없도록 보장된다. 이를 통해 특정 레코드를 조회하는 동안 해당 레코드를 다른 트랜잭션이 수정하는 것을 방지할 수 있다.
- Repeatable Read :
Repeatable Read 격리 수준은트랜잭션에서 같은 쿼리를 반복 실행할 때 항상 동일한 결과를 보장한다. 따라서 다른 트랜잭션에 의해 해당 레코드가 수정되는 것을 완전히 방지했다. 그렇기 때문에 특정 레코드를 조회하는 동안 해당 레코드를 수정하지 못하도록 격리할 수 있다.
- Serializable :
Serializable 격리 수준은 가장 높은 격리 수준으로, 모든 트랜잭션들이 직렬화되어 실행된다. 즉 동시에 여러 트랜잭션이 실행될 때, 순차적으로 실행되어야 한다. 따라서 다른 트랜잭션에 의해 해당 레코드가 수정되는 것을 완전히 방지할 수 있다.
유익한 글이었습니다.