기타

CUBRID isolation level & Dirty Read

by 정만영 posted May 29, 2015

1, CUBRID Isolation level이란

CUBRID는 트랜잭션의 격리 수준(isolation level)을 지정하여 덜 제한적인 일관성(consistency)으로 트랜잭션을 수행하도록 한다, 트랜잭션의 격리수준은 트랜잭션이 동시에 진행중인 다른 트랜잭션에 의해 간섭을 받는 정도를 의미하며 CUBRIDSchemaInstances 조합해 isolation level을 적용한다.

 

2, Dirty Read

CUBRIDcubrid.conf에 설정된 격리수준의 기본값은 REPEATABLE READ CLASS, READ UNCOMMITTED INSTANCES로 데이터를 읽을 때 Dirty read가 발생한다.

Dirty Read T1 트랜잭션에서 읽기하고 실행이 끝나지 않은 상태에서 T2 트랜잭션에 의해 변경된 사항을 보게 되는 경우를 dirty read라고 한다, 만약 T2 트랜잭션에서 그 변경 사항을 rollback하면 그 데이터를 읽은 T1 트랜잭션은 Dirty 데이터를 가지고 있는 것이다.

CUBRIDDirty Read를 방지하기 위해서 아래 CUBRID isolation level 표를 확인해 isolation 변경이 필요하다.

  • INSTANCES isolation Level Dirty Read 결과표

Isolation Level

T2Commit/Rollback 수행할 경우 결과

T2Commit/Rollback 수행하지 않을 경우 결과

READ UNCOMMITTED INSTANCES

가능

가능

READ COMMITTED INSTANCES

불가능

불가능

REPEATABLE READ INSTANCES

불가능

불가능

SERIALIZABLE

불가능

불가능


3, isolation level 환경 설정

CUBRID isolation level 기본설정 값은 REPEATABLE READ CLASS, READ UNCOMMITTED INSTANCEScubrid.confisolation_level로 파라미터로 환경 설정이 가능하고 변경한 설정은 데이터베이스 서버 재구동 후 isolation level(격리수준)이 반영된다.

$>vi $CUBRID/conf/cubrid.conf

isolation_level = 1

à 격리수준 변경은 아래 표를 참조해 설정한다.

  • CUBRID isolation level 정리표

CUBRID 격리수준 (isolation_level)

DBMS 격리 수준

더티 읽기

조회 중인 테이블에 대한 스키마 갱신

SERIALIZABLE (6)

SERIALIZABLE

X

X

REPEATABLE READ CLASS with REPEATABLE READ INSTANCES (5)

REPEATABLE READ

X

X

REPEATABLE READ CLASS with READ COMMITTED INSTANCES (4)

READ COMMITTED

X

X

REPEATABLE READ CLASS with READ UNCOMMITTED INSTANCES (3)

READ UNCOMMITTED

O

X

READ COMMITTED CLASS with READ COMMITTED INSTANCES (2)

-

X

O

READ COMMITTED CLASS with READ UNCOMMITTED INSTANCES (1)

-

O

O


4, 트랜잭션별 격리수준 설정과 확인

csql 인터프린터에서 다음과 같이 스키마와 Instances를 콤마(,) 구분하여 변경한다.

구문: SET TRANSACTION ISOLATION LEVEL isolation_level_spec

csql>SET TRANSACTION ISOLATION LEVEL REPEATABLE READ CLASS, REPEATABLE READ INSTANCES;

csql>SET TRANSACTION ISOLATION LEVEL READ COMMITTED CLASS, READ UNCOMMITTED INSTANCES;

현 트랜잭션 isolation level 값을 얻고자 할 경우 GET TRANSACTION 문을 이용해 아래와 같이 얻을 수 있다.

구문: GET TRANSACTION ISOLATION LEVEL

csql> GET TRANSACTION ISOLATION LEVEL

csql> ;x

=== <Result of GET ISOLATION LEVEL Command in Line 2> ===

       Result

=============

  READ COMMITTED SCHEMA, READ UNCOMMITTED INSTANCES


5, JAVA 프로그램 트랜잭션 격리수준 변경

데이터베이스 읽기 수행 시 Dirty Read 방지가 필요하다면 isolation levelREAD COMMITTED INSTANCES 편경해야 한다, 하지만 데이터베이스 전체의 격리수준을 높일 경우 서비스에 성능적인 영향을 크게 받을 수 있다, 이런 상황에서는 서비스 영향에 따라 특정 트랜잭션이나 질의만을 선택적으로 Dirty Read가 발생되지 않도록 conn.setTransactionIsolation(); 함수로 isolation level을 조정해  Dirty Read를 방지할 수 있다.

Ex) JAVA 프로그램 conn.setTransactionIsolation(); 함수 사용예제

import java.sql.*;

public class SelectData {

   public static void main(String[] args) throws Exception {

       Connection conn = null;

       Statement stmt = null;

       ResultSet rs = null;

       ResultSet ri = null;

       try {

       Class.forName("cubrid.jdbc.driver.CUBRIDDriver");

       conn = DriverManager.getConnection("jdbc:cubrid:localhost:30000:demodb:::","dba","");

        System.out.println("conn_isolation_level-->" + conn.getTransactionIsolation());

        conn.setTransactionIsolation(2);   // isolation level à COMMITTED INSTANCES 변경

        System.out.println("set_isolation_level-->" + conn.getTransactionIsolation());

       String sql = "select name from event where rownum=1";

       stmt = conn.createStatement();

       rs = stmt.executeQuery(sql);

       while(rs.next()) {

           String name = rs.getString("name");

           System.out.println("");

           System.out.println("============================================");

           System.out.println("name ==> " + name);

           System.out.println("============================================");

           System.out.println("");

       }

        conn.setTransactionIsolation(1);  // isolation level à UNCOMMITTED INSTANCES 원복

       rs.close();

       stmt.close();

       conn.close();

       } catch ( SQLException e ) {

           System.err.println(e.getMessage());

       } catch ( Exception e ) {

           System.err.println(e.getMessage());

       } finally {

           if ( conn != null ) conn.close();

       }

   }

}


참조1: conn.setTransactionIsolation(); 함수로 변경된 트랜잭션은 CAS 프로세서가 변경된 isolation level을 유지하기 때문에 WASconnection pool을 사용할 경우는 반드시 conn.setTransactionIsolation(); 함수로 현재 설정된 isolation level로 원복이 필요하다.


참조2: conn.setTransactionIsolation 설정값과 격리수준은 다음과 같다.

setTransactionIsolation(1): REPEATABLE CLASSES AND READ UNCOMMITTED INSTANCES

setTransactionIsolation(2): REPEATABLE CLASSES AND READ COMMITTED INSTANCES

setTransactionIsolation(3): Unknown transaction isolation level

setTransactionIsolation(4): REPEATABLE CLASSES AND REPEATABLE INSTANCES





Articles

1 2 3 4 5 6 7 8 9