SERIALIZABLE

이 격리 수준에서는 모든 동시성 관련 문제들, 즉 더티 읽기, 반복 불가능한 읽기, 유령 읽기 등이 발생하지 않는다.

다음과 같은 규칙이 적용된다.

이 격리 수준은 2단계 잠금 프로토콜을 따른다.

예제

다음 예제는 한 트랜잭션은 어떤 클래스에 인스턴스를 삽입하고, 다른 트랜잭션은 특정 검색 조건으로 검색하는 트랜잭션이 있는 경우이다. 트랜잭션 T1은 임의의 트랜잭션 격리 수준이고, T2는 SERIALIZABLE 격리 수준이다. 여기서 participant2 클래스는 기존에 생성되지 않은 것을 가정한다.

  1. T1이 participant2 클래스를 생성하고 host_year, nation_code 속성에  유일 키(unique key)를 생성하고 몇 개의 인스턴스들을 삽입한다. T1이 커밋한 후에 CUBRID는 T1에 의해 획득된 모든 잠금들을 해제한다. 그리고, T2가 participant2 에 대해 nation_code = ‘AUS’ 라는 조건으로 검색한다.
    1. set transaction isolation level serializable;
      ;autocommit off
      create class participant2 (host_year integer, nation_code char(3));
      create unique index on participant2 (host_year, nation_code);
      insert into participant2 (host_year, nation_code) values (2008, ‘AUS’);
      commit work;
      ;xrun
      1 rows inserted.
      1. User2 (T2)
    2. set transaction isolation level serializable;
      ;autocommit off
      select * from participant2 where nation_code=’AUS’;
      ;xrun
      1 rows selected.
  2. 이때, T1이 (2004, ‘AUS’)인 인스턴스를 participant2 클래스에 삽입하려고 하면 T2가 nation_code = ‘AUS’라는 조건으로 검색하고 나서 아직 COMMIT WORK 문을 수행하지 않았기 때문에 대기한다. T2가 커밋을 하여 모든 잠금들을 해제하면 대기하였던 T1이 수행된다. T2가 나중에(------ 2nd 이하) 다시 같은 조건으로 검색하면 T1이 아직 삽입한 인스턴스에 대해 잠금을 획득하고 있으므로 대기 상태가 된다.
    1. insert into participant2 (host_year, nation_code) values (2004, ‘AUS’);
      ;xrun
      ------ 1st
      1 rows inserted.
      1. User2 (T2):
    2. select host_year, nation_code from participant2 where nation_code=’AUS’;
      ;xrun
      === <Result of SELECT Command in Line 1> ===
          host_year  nation_code
      =====================================
               2008  'AUS'  
      1 rows selected.

      commit work;
      ;xrun
      1 command(s) successfully processed.
      ------ 2nd
      select host_year, nation_code from participant2 where nation_code=’AUS’;
      ;xrun
  3. 다시 T1이 커밋하면 잠금이 해제되면서 T2가 수행되어 SELECT 문의 결과를 볼 수 있게 된다.
    1. commit work;
      ;xrun
      1. User2 (T2):
    2. === <Result of SELECT Command in Line 1> ===
          host_year  nation_code
      ===================================
               2008  'AUS'
               2004  'AUS'
      2 rows selected
      .
  4. T1이 participant2 클래스를 nation_medals 클래스로 이름을 갱신하려고 하면 T2가 커밋되지 않았기 때문에 대기하게 된다.
    1. rename class participant2 as nation_medals;
      ;xrun
  5. T2가 커밋하면(a) T1이 다시 진행되어 participant2 클래스를 nation_medals 클래스로 갱신한다. T1이 커밋되고(b), T2가 participant2 클래스에 대한 SELECT 문이 수행되면(c) participant2 클래스는 더 이상 존재하지 않으므로 구문 에러가 발생한다.
    1. commit work;
      ;xrun
      ---------------------------------------------------------------------------(a)
      select * from participant2 where nation_code = ’AUS’;
      ;xrun
      ---------------------------------------------------------------------------(c)
      In line 1, column 1,
      ERROR: Unknown class "participant2".
      1. User 1 (T1):
    2. commit work;
      ;xrun
      ---------------------------------------------------------------------------(b)