ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Postgresql에서의 Transaction 종류
    PostgreSQL 2014. 6. 18. 09:00
    반응형

    표준 트랜잭션 레벨

     

    표준 트랜잭션에는 4가지 레벨이 있지만 PostgreSQL에서는 3가지만 지원함. 

    • phenomena 종류

        dirty read : 트랜잭션이 현재 커밋되지 않은 트랜잭션에서 작성된 데이터를 읽는다.
        nonrepeatable read : 트랜잭션은 자신이 실행된 후 최근 커밋된 다른 트랜잭션이 이전에 읽었던 데이터를 수정했으면 그 데이터를 다시 읽는다.
        phantom read : 트랜잭션의 로우가 최근 커밋된 트랜잭션에서 변경되어서 조건을 만족시키는 로우의 집합이 변경된 경우, 로우의 집합을 다시 얻기위해 트랜잭션이 쿼리를 다시 실행한다.
     
     

    • 표준 SQL 트랜잭션 레벨
    Isolation LevelDirty ReadNonrepeatable ReadPhantom Read
    Read uncommitted가능함가능함가능함
    Read committed불가능가능함가능함
    Repeatable read불가능불가능가능함
    Serializable불가능불가능불가능

     

    PostgreSQL에서의 트랜잭션 레벨

     Read Committed Isolation Level

    PostgreSQL에서의 기본 레벨.

    • SELECT 쿼리

    쿼리가 시작했을 당시의 커밋된 데이터만 참조할 수 있음.
    쿼리가 실행되는 도중에 커밋되지 않은 데이터 혹은 동시에 실행되고 있던 트랜잭션에서 커밋된 변경들은 참조하지 않음.
    외부 트랜잭션이 아닌 자신의 트랜잭션 도중에 일어난 커밋되지 않은 수정 사항은 참조할 수 있음.
    트랜잭션내부에서 SELECT가 여러번 있을 때, 각 SELECT 쿼리 사이에 외부 트랜잭션이 커밋을 했으면 커밋된 다음에 실행된 SELECT 쿼리는 커밋된 데이터를 참조하게 됨.

    • UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR SHARE 쿼리

    SELECT 쿼리와 동일하게 동작함.
    단지 데이터를 변경하는 도중에 다른 트랜잭션이 같은 로우에 접근하면 그 트랜잭션이 끝난 후에 변경사항에 대해서 작업을 진행하게 됨.
    이 때, 외부 트랜잭션 때문에 변경된 로우가 현재 명령의 WHERE 조건에 맞는지 다시 평가를 하게 됨.
    Read Committed는 복잡한 검색 조건이 있는 상황에는 맞지 않고, 은행 잔고 변경같은 단순한 경우에 적합함. 

    Repeatable Read Isolation Level

    • SELECT 쿼리

    현재 트랜잭션이 시작하기전에 커밋된 데이터만 참조함.
    외부 트랜잭션에서 커밋되거나 커밋되지 않은 변경을 참조하지 않음.
    외부 트랜잭션이 아닌 자신의 트랜잭션 도중에 일어난 커밋되지 않은 수정 사항은 참조할 수 있음.
     
    Read Committed하고의 차이점은 현재 트랜잭션에 여러번의 쿼리가 있을 경우, 현재 트랜잭션의 쿼리 중간에 다른 트랜잭션에서 변경이 있었더라도 참조하지 않고, 현재 트랜잭션이 시작되었을때의 데이터와 현재 트랜잭션이 수행되던 도중에 일어난 변경사항만 참조함.
     
    이 레벨을 사용하게 되면 실패했을 때 재시도하는걸 애플리케이션에서 처리해 주어야 함.
     

    • UPDATE, DELETE, SELECT FOR UPDATE, SELECT FOR SHARE 쿼리

    데이터를 변경하는 도중에 다른 트랜잭션이 같은 로우에 접근하면 그 트랜잭션이 끝난후에 변경하려던 로우가 변경됐는지 확인해서
    변경사항이 없으면 원래 진행하려던 명령을 실행하고, 변경됐으면 다음과 같은 에러메시지를 내면서 트랜잭션을 롤백함.
    ERROR:  could not serialize access due to concurrent update
     
    읽기만 하는 트랜잭션에서는 에러가 없음.

    Serializable Isolation Level

    가장 엄격한 트랜잭션 레벨
    트랜잭션들이 동시에 일어나지 않고, 하나씩 순서대로 실행되는 것 처럼 작동함.
    그래도, Repeatable Read 레벨처럼 애플리케이션에서 실패했을 때 재시도 처리를 해주어야 함.
    Repeatable Read와 동일하게 작동하면서 트랜잭션들이 순서대로 실행중인지 모니터링함.
    잘 고려하지 않으면 성능저하가 있을 수 있음.

    트랜잭션 시스템 구조

     
    Postgresql의 트랜잭션 시스템은 3개의 레이어로 구성되어 있음.
    상단 레이어는 사용자가 SQL 명령어를 통해서 시스템의 상태를 변경할 수 있게 됨.
    중단 레이어(middle layer)는 개별 쿼리를 프로세싱하는 전과 후를 담당함.
    하단 레이어(bottom layer)는 로우레벨 트랜잭션과 서브 트랜잭션을들 구현함. 

     

    상단 레이어

    사용자가 BEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK TO, RELEASE등의 명령을 실행하면 각각 아래의 상태로 매칭되게 됨.

    BEGIN: BeginTransactionBlock
    COMMIT: EndTransactionBlock
    ROLLBACK : UserAbortTransactionBlock
    SAVEPOINT : DefineSavepoint
    ROLLBACK TO : RollbackToSavepoint
    RELEASE : ReleaseSavepoint
     

    중단 레이어의 상태 단계

    StartTransactionCommand
    CommitTransactionCommand
    AbortCurrentTransaction
     

    하단 레이어에서 실제로 호출되는 함수들

    StartTransaction
    CommitTransaction
    AbortTransaction
    CleanupTransaction
    StartSubTransaction
    CommitSubTransaction
    AbortSubTransaction
    CleanupSubTransaction
    CommandCounterIncrement 
     

    실제 트랜잭션이 실행되는 모습

    아래와 같은 트랜잭션 명령을 실행하면
    1) BEGIN
    2) SELECT * FROM foo
    3) INSERT INTO foo VALUES (...)
    4) COMMIT
     
    실제로 DB에서는 다음과 같은 순서로 함수들을 호출하면서 트랜잭션이 처리되게 됨.

     

           /  StartTransactionCommand;
          /       StartTransaction;
    1) <        ProcessUtility;                           << BEGIN
          \       BeginTransactionBlock;
           \  CommitTransactionCommand;

         /   StartTransactionCommand;
    2) /        ProcessQuery;                          << SELECT ...
        \        CommitTransactionCommand;
         \       CommandCounterIncrement;

         /   StartTransactionCommand;
    3) /        ProcessQuery;                          << INSERT ...
        \        CommitTransactionCommand;
         \       CommandCounterIncrement;

          /  StartTransactionCommand;
         /   ProcessUtility;                              << COMMIT
    4) <            EndTransactionBlock;
         \   CommitTransactionCommand;
          \      CommitTransaction;

     


    트랜잭션 취소는 2가지 경우에 일어날 수 있음.

    1) 시스템 다운
    2) 사용자가 롤백함.
     
    첫번째 시스템 다운의 경우에는 중단 레이어의 AbortCurrentTransaction이 처리하고, 두번째 사용자 롤백의 경우에는 상단 레이어의 UserAbortTransactionBlock에서 처리함.
    둘 다 실제 처리는 하단 레이어의 AbortTransaction 함수를 통해 처리함.
    둘 사이의 차이점은 AbortCurrentTransaction는 TBLOCK_ABORT상태(ROLLBACK을 기다리는 상태, 다시 실패할 가능성이 있음.)이고, UserAbortTransactionBlock는 TBLOCK_ABORT_END 상태(ROLLBACK을 받은 상태. 자원을 정리하기만 하면 됨.)임.
     
    실제로 트랜잭션을 취소하는 단계는 AbortTransaction와 CleanupTransaction 함수 호출을 통해서 일어남.
     
    AbortTransaction은 락(lock)된 모든 공유자원을 해제해서, 불필요한 다른 백엔드 지연이 발생하지 않게 함.
    CleanupTransaction은 사용자가 COMMIT이나 ROLLBACK 명령을 실행했을 때 실행됨. 트랜잭션에 관련된 자원들을 정리함.

     

    References


    반응형

    'PostgreSQL' 카테고리의 다른 글

    Postgresql 바이너리 데이터 입력  (0) 2011.01.30
    cannot open shared object file 메세지 해결  (0) 2011.01.06
    postgres 팁  (0) 2010.11.25
    postgresql.conf 설정내용  (0) 2010.11.25
    plpgsql 등록, 설정  (0) 2010.05.03

    댓글

Designed by Tistory.