원자성, 일관성, 고립성, 지속성
원자성 (Atomicity)
-
사전적 의미
원자성은 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 능력이다.
즉, 작업이 중간 단계까지만 실행되고 실패하는 일이 없도록 하는 것이다. -
기능적 의미
원자적 연산을 보장해야 한다. ⇒ All or Nothing
MySQL에서는
MVCC를 통해 지원해 준다.트랜잭션이 Atomicity한 단위가 된다.
일관성 (Consistency)
-
사전적 의미
트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것
-
기능적 의미
트랜잭션의 종료되었을 때 데이터 무결성 보장된다.
제약조건을 통해 ⇒ 유니크 제약, 외래키 제약 등
고립성(Isolation)
-
사전적 의미
트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것을 의미한다. 이것은 트랜잭션 밖에 있는 어떤 연산도 중간 단계의 데이터를 볼 수 없음을 의미한다.
성능관련 이유로 인해 이 특성은 가장 유연성 있는 제약 조건이다.
-
기능적 의미
트랜잭션은 서로 간섭하지 않고 독립적으로 동작한다. ⇒ 하지만 많은 성능을 포기해야 하므로 개발자가 제어 가능 ⇒ 트랜잭션 격리레벨을 통해 제거 (
Undo log와MVCC)
지속성(Durability)
-
사전적 의미
성공적으로 수행된 트랜잭션은 영원히 반영되어야 함을 의미한다. 시스템 문제, DB 일관성 체크 등을 하더라도 유지되어야 함을 의미한다. 전형적으로 모든 트랜잭션은 로그로 남고 시스템 장애 발생 전 상태로 되돌릴 수 있다. 트랜잭션은 로그에 모든 것이 저장된 후에만 commit 상태로 간주될 수 있다.
-
기능적 의미
완료된 트랜잭션은 유실되지 않는다.
WAL(Write ahead logging)을 통해서 이루어진다.- WAL (Write ahead loggin)
> 트랜잭션이 일어나기 전에 로그를 미리 기록하여 트랜잭션 undo, redo를 할 수 있도록 한다.
> 변경을 로깅한 후에만, 즉 변경 내용을 설명한는 로그 레코드를 영구적 저장소에 먼저 기록한 후에 데이터 파일(테이블과 인덱스가 있는)의 변경 내용을 작성해야 한다는 것이다.
> 위의 내용을 준수한 경우 충돌 발생 시 로그를 사용하여 데이터베이스를 복수할 수 있으므로 트랜잭션 커밋마다 데이터 페이지를 디스크에 쓸 필요가 없다. 데이터 페이지에 적용되지 않은 변경 내용은 로그 레코드에서 실행 취소가 가능하다.
- WAL (Write ahead loggin)
동시에 여러 트랜잭션이 진행될 때 트랜잭션의 작업 결과를 여타 트랜잭션에게 어떻게 노출할 것인지를 결정한다.
-
- 정의 트랜잭션이 아직 커밋되지 않은 다른 트랜잭션의 변경 내용을 읽는 것을 Dirty Read라고 합니다.
- 설명
하나의 트랜잭션이 데이터를 변경하고 아직 커밋하지 않은 상태에서, 다른 트랜잭션이 해당 변경된 데이터를 읽게 되면 더티 리드가 발생합니다.
이 경우, 첫 번째 트랜잭션이 롤백되면 읽은 데이터가 사라지기 때문에 데이터 무결성이 깨질 수 있습니다.
-
-
정의
하나의 트랜잭션이 같은 데이터를 두 번 읽을 때, 중간에 다른 트랜잭션이 해당 데이터를 변경하고 커밋하여 두 번의 읽기 결과가 다른 경우를 Non Repeatable Read라고 합니다.
-
설명
트랜잭션이 동일한 데이터를 여러 번 읽을 때, 중간에 다른 트랜잭션이 해당 데이터를 수정하고 커밋하면 첫 번째 읽을 결과와 두 번째 읽은 결과가 다를 수 있습니다.
-
-
-
정의
트랜잭션이 범위 내의 데이터를 읽을 때, 중간에 다른 트랜잭션이 데이터를 추가 또는 삭제하여 트랜잭션이 읽은 데이터 집합이 변경되는 경우
-
설명
트랜잭션이 범위 내의 데이터를 읽을 때, 범위에 속하는 데이터가 다른 트랜잭션에 의해 추가되거나 삭제되면, 처음에는 없던 데이터가 나타나거나 사라질 수 있습니다.
-
| Isolation level | Dirty Read | Non-repeatable read | Phantom read |
|---|---|---|---|
| Read uncommitted | Y | Y | Y |
| Read comitted | N | Y | Y |
| Repeatable read | N | N | Y |
| Serializable | N | N | N |
- DEFAULT
- 사용하는 데이터 엑세스 기술 또는 DB 드라이버의 디폴트 설정에 따름
- 일반적으로 드라이버 격리 수준은 DB의 격리 수준을 따르며, 대부분의 DB는 READ_COMMITED를 기본 격리 수준으로 가짐
- READ_UNCOMMITTED (읽기 미확정)
- 가장 낮은 격리수준으로써 하나의 트랜잭션이 커밋되기 전에 그 변화가 다른 트랜잭션에 그대로 노출되는 문제를 가진다.
- 가장 빠른 속도를 가지므로 데이터의 일관성이 떨어지더라도 의도적으로 사용될 수 있다.
- Dirty Read, Phantom Read, Non-Repeatable Read 문제
- READ_COMMITTED (읽기 확정)
- Spring은 기본 속성이 DEFAULT이며, DB는 일반적으로 READ_COMMITED가 기본 속성으로 사용된다.
- 가장 많이 사용되는 속성이다.
- READ_UNCOMMITED와 달리 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없다.
- 하나의 트랜잭션이 읽은 로우를 다른 트랜잭션이 수정할 수 있어서 처음 트랜잭션이 같은 로우를 다시 읽을 때 다른 내용이 발견딜 수 있음
- Phantom Read, Non-Repeatable Read 문제
- REPEATABLE_READ (반복 가능한 읽기)
- 하나의 트랜잭션이 읽은 로우를 다른 트랜잭션이 수정할 수 없도록 막아주지만 새로운 로우를 추가하는 것은 막지 않는다.
- 따라서 SELECT로 조건에 맞는 로우를 전부 가져오는 경우 트랜잭션이 끝나기 전에 추가된 로우를 발견할 수 없다.
- Phantom Read 문제
- SERIALIZABLE (직렬화 가능한 읽기)
- 가장 강력한 트랜잭션 격리 수준으로, 이름 그대로 트랜잭션을 순차적으로 진행시켜준다.
- SERIALIZABLE 은 여러 트랜잭션이 동시에 같은 테이블의 정보를 엑세스 할 수 없다.
- SERIALIZABLE 은 가장 안전하지만 가장 성능이 떨어지므로 극단적으로 안전한 작업이 필요한 경우가 아니라면 사용해서는 안된다.


