트랜잭션의 격리성(Isolation)을 완벽히 보장하려면 트랜잭션을 차례대로 실행해야 한다. 이렇게 하면 동시성 처리 성능이 나빠지게 된다. 이런 문제로 인해 트랜잭션의 격리 수준(Isolation Level)을 4단계로 나누어 정의하였다.

- READ UNCOMMITED(커밋되지 않은 읽기): 커밋하지 않은 데이터를 읽을 수 있다. 예를 들어 트랜잭션A가 데이터를 수정하고 있을 때 커밋되지 않아도 트랜잭션B가 수정 중인 데이터를 조회할 수 있다. 이것을 DIRTY READ라 한다. 트랜잭션B가 DIRTY READ한 데이터를 사용하는데 트랜잭션A를 롤백하면 데이터 정합성에 심각한 문제가 발생할 수 있다. 이런 DIRTY READ를 허용하는 격리 수준을 READ UNCOMITTED라 한다.
- READ COMMITED(커밋된 읽기): 커밋한 데이터만 읽을 수 있다. 따라서 DIRTY READ를 허용하지 않는다. 하지만 NON-REPEATABLE READ는 발생할 수 있다. 예를 들어 트랜잭션A가 회원1을 조회 중인데 트랜잭션B가 회원1을 수정하고 커밋하면 트랜잭션A가 다시 회원1을 조회했을 때 수정된 데이터가 조회된다. 이처럼 반복해서 같은 데이터를 읽을 수 없는 상태를 NON-REPEATABLE READ라 한다. NON-REPEATABLE READ를 허용하는 격리 수준을 READ COMMITED라 한다.
- REPEATABLE READ(반복 가능한 읽기): 한 번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회된다. 하지만 PHANTOM READ는 발생한다. 예를 들어 트랜잭션A가 10살 이하의 회원을 조회했는데 트랜잭션B가 10살 이하의 회원을 추가하고 커밋하면 트랜잭션A가 다시 10살 이하의 회원을 조회했을 때 회원 하나가 추가된 상태로 조회된다. 이처럼 반복 조회 시 결과 집합이 달라지는 것을 PHANTOM READ라 한다. PHANTOM READ를 허용하는 격리 수준을 REPEATABLE READ라 한다.
- SERIALIZABLE(직렬화 가능): 가장 엄격한 트랜잭션 격리 수준으로 PHANTOM READ 조차 허용하지 않는다. 하지만 동시성 처리 성능이 급격히 떨어질 수 있다.
애플리케이션 대부분은 동시성 처리가 중요하므로 데이터베이스들은 보통 READ COMMITED 격리 수준을 기본으로 사용한다. 일부 중요한 비즈니스 로직에 더 높은 격리 수준이 필요하면 데이터베이스 트랜잭션이 제공하는 잠금 기능을 사용하면 된다.
자바 ORM 표준 JPA 프로그래밍(김영한) 참고