트랜잭션 격리 레벨

트랜잭션 격리 레벨은 트랜잭션 내 명령문에 표시되는 데이터를 지정합니다. 이러한 레벨은 동일한 대상 데이터 소스에 대한 트랜잭션 간 발생할 수 있는 상호작용을 정의하여 동시액세스의 레벨에 직접적으로 영향을 줍니다.

데이터베이스 이상 항목

데이터베이스 이상 항목은 단일 트랜잭션의 범위에서 볼 때 부정확해 보이지만 모든 트랜잭션의 범위에서 볼 때 정확한 생성 결과입니다. 다른 유형의 데이터베이스 이상 항목은 다음과 같이 설명됩니다.

  • 더티 읽기는 다음의 경우에 발생합니다.
    1. 트랜잭션 A 가 행을 테이블에 삽입합니다.
    2. 트랜잭션 B가 새 행을 읽습니다.
    3. 트랜잭션 A가 롤백합니다.

    트랜잭션 B는 트랜잭션 A가 삽입한 행을 기반으로 시스템에 대한 작업을 수행했을 수도 있지만 해당 행은 데이터베이스의 영구적 일부가 되지 않습니다.

  • 비반복 읽기는 다음의 경우에 발생합니다.
    1. 트랜잭션 A가 행을 읽습니다.
    2. 트랜잭션 B가 행을 읽습니다.
    3. 트랜잭션 A가 같은 행을 두 번 읽고 새 결과를 얻습니다.
  • 팬텀 읽기는 다음의 경우에 발생합니다.
    1. 트랜잭션 A가 SQL 쿼리의 WHERE 절을 충족시키는 모든 행을 읽습니다.
    2. 트랜잭션 B가 WHERE 절을 충족시키는 추가 행을 삽입합니다.
    3. 트랜잭션 A가 WHERE 조건을 다시 평가하고 추가 행을 선택합니다.
참고: i용 DB2®는 그 잠금 전략으로 인해 규정된 레벨에서 애플리케이션을 허용 가능한 데이터베이스 이상 항목에 항상 노출시키지는 않습니다.

JDBC 트랜잭션 격리 레벨

IBM® Developer Kit for Java™ JDBC API에는 다섯 개의 트랜잭션 격리 레벨이 있습니다. 이러한 격리 레벨은 다음과 같이 가장 제한적이지 않은 레벨부터 가장 제한적인 레벨까지 나열됩니다.

JDBC_TRANSACTION_NONE
이는 JDBC 드라이버가 트랜잭션을 지원하지 않음을 나타내는 특수 상수입니다.
JDBC_TRANSACTION_READ_UNCOMMITTED
이 레벨에서는 데이터에 대한 커미트되지 않은 변경을 보기 위한 트랜잭션이 허용됩니다. 모든 데이터베이스 이상 항목이 이 레벨에서 가능합니다.
JDBC_TRANSACTION_READ_COMMITTED
이 레벨은 트랜잭션 내부에서 작성된 변경은 트랜잭션이 커미트될 때까지 외부에 표시되지 않음을 의미합니다. 이는 더티 읽기가 가능해지는 것을 방지합니다.
JDBC_TRANSACTION_REPEATABLE_READ
이 레벨은 트랜잭션이 완료되지 않으면 다른 트랜잭션을 변경할 수 없도록 읽혀지는 행이 잠금을 보유함을 의미합니다. 이는 더티 읽기 및 비반복 읽기를 허용하지 않습니다. 팬텀 읽기는 계속 가능합니다.
JDBC_TRANSACTION_SERIALIZABLE
값을 테이블에 추가하거나 테이블에서 제거하는 다른 트랜잭션이 WHERE 조건을 변경할 수 없도록 테이블은 트랜잭션에 대해 잠겨집니다. 이는 모든 유형의 데이터베이스 이상 항목을 방지합니다.

setTransactionIsolation 메소드를 사용하여 연결의 트랜잭션 격리 레벨을 변경할 수 있습니다.

고려사항

공통적인 잘못된 해석은 JDBC 스펙이 이전에 언급한 다섯 개의 트랜잭션 레벨을 정의한다는 것입니다. TRANSACTION_NONE 값이 커미트 제어 없이 실행하는 개념을 나타내는 것으로 생각하는 경우가 많습니다. JDBC 스펙은 같은 방식으로 TRANSACTION_NONE을 정의하지 않습니다. TRANSACTION_NONE은 JDBC 스펙에서 드라이버가 트랜잭션을 지원하지 않고 JDBC 준수 드라이버가 아닌 레벨로 정의됩니다. NONE 레벨은 getTransactionIsolation 메소드가 호출되는 경우 보고되지 않습니다.

이 문제는 JDBC 드라이버의 디폴트 트랜잭션 격리 레벨이 구현에 의해 정의된다는 사실에 의해 약간 복잡해집니다. 원시 JDBC 드라이버의 디폴트 트랜잭션 격리 레벨은 NONE입니다. 이 레벨에서는 드라이버가 저널이 없는 파일에 대해 작업할 수 있고 QGPL 라이브러리의 파일과 같은 스펙을 작성하지 않아도 됩니다.

원시 JDBC 드라이버를 사용하면 JDBC_TRANSACTION_NONE을 setTransactionIsolation 메소드에 전달하거나 연결 특성으로 없음을 지정할 수 있습니다. 그러나 getTransactionIsolation 메소드는 값이 없음일 때 항상 JDBC_TRANSACTION_READ_UNCOMMITTED를 보고합니다. 실행 중인 레벨을 계속해서 추적하는 것이 애플리케이션의 요구사항인 경우 이는 애플리케이션의 책임입니다.

이전 릴리스에서는 시스템에 진짜 자동 커미트 모드에 대한 개념이 없었기 때문에 JDBC 드라이버가 트랜잭션 격리 레벨을 없음으로 변경하여 자동 커미트에 대해 true를 지정하도록 처리했을 것입니다. 이는 기능 면에서 매우 비슷하지만 모든 시나리오에 대해 올바른 결과를 제공하지는 않습니다. 이는 더 이상 수행되지 않으며 데이터베이스는 자동 커미트의 개념을 트랜잭션 격리 레벨의 개념으로부터 분리합니다. 따라서 자동 커미트가 작동 가능으로 설정된 JDBC_TRANSACTION_SERIALIZABLE 레벨에서 실행하는 것은 완전히 유효합니다. 유효하지 않은 유일한 시나리오는 JDBC_TRANSACTION_NONE 레벨에서 실행하고 자동 커미트 모드 상태가 아닌 것입니다. 애플리케이션은 시스템이 트랜잭션 격리 레벨에서 실행되지 않는 경우에 커미트 경계에 대해 제어할 수 없습니다.

JDBC 스펙과 IBM i 플랫폼 사이의 트랜잭션 격리 레벨

IBM i 플랫폼에는 JDBC 스펙에서 제공되는 트랜잭션 격리 레벨 이름과 일치하지 않는 트랜잭션 격리 레벨의 공통 이름이 있습니다. 다음 테이블은 IBM i 플랫폼에서 사용되는 이름과 일치하지만 JDBC 스펙에서 사용되는 이름과는 같지 않습니다.

JDBC 레벨* IBM i 레벨
JDBC_TRANSACTION_NONE *NONE 또는 *NC
JDBC_TRANSACTION_READ_UNCOMMITTED *CHG 또는 *UR
JDBC_TRANSACTION_READ_COMMITTED *CS
JDBC_TRANSACTION_REPEATABLE_READ *ALL 또는 *RS
JDBC_TRANSACTION_SERIALIZABLE *RR

* 이 테이블에서 JDBC_TRANSACTION_NONE 값은 명확성을 위해 IBM i 레벨 *NONE 및 *NC와 함께 정렬됩니다. 이는 직접적인 스펙 대 IBM i 레벨 일치가 아닙니다.