Database/MS-SQL

격리수준 (ISOLATION)

ㅈㅣ니 2024. 9. 24.

격리수준(ISOLATION)이란?

트랜잭션이 수행될 때 다른 트랜잭션으로부터 영향을 받지 않게 고립성을 유지시키는 트랜잭션 특징입니다.

다른 트랜잭션에 영향을 받지 않도록 잠금(Lock)을 사용하며 트랜잭션 작업에 대한 고립성을 유지하기 위해 다양한 격리 수준으로 잠금의 유형을 정의합니다.

즉, 여러 트랜잭션이 동시에 수행될 때 한 트랜잭션에서 조회 또는 변경되는 데이터에 대해 다른 트랜잭션에서 접근 가능한 수준을 정하는 것입니다

 

기본 격리 수준은 READ COMMITTED 이며, 격리 수준 옵션을 지정하는 구문은 다음과 같습니다.

SET TRANSACTION ISOLATION LEVEL
{
	READ UNCOMMITTED
	| READ COMMITTED
	| REPEATABLE READ
	|SNAPSHOT
	| SERIALIZABLE
}

 

 

격리 수준의 필요성

트랜잭션이 다른 트랜잭션에 영향을 받지 않도록 하기 위해 잠금으로 이를 보장하며 트랜잭션의 격리 수준을 높이면 동시성은 낮아지고 반대로 격리 수준을 낮추면 동시성은 높아집니다.

동시성 제어를 위해서는 다양한 격리 수준이 필요하며 상황에 따라 적합한 수준을 사용해야 합니다.

동시성에 대한 3가지 문제점은 다음과 같습니다.

 

동시성에 대한 3가지 문제점(Dirty Read, Non-Repetable Read, Phantom Read)

  1. Dirty Read
    트랜잭션에서 데이터를 읽을 때 다른 트랜잭션에서 아직 COMMIT 되지 않은 데이터를 읽는 현상입니다.
    Dirty Read

    Session 2에서 TB_D 테이블의 no =1인 데이터를 조회해서 Grade가 A 인 것을 확인 후Session 1에서는 READ UNCOMMITTED 격리 수준으로 동일한 데이터를 조회하여그 결과 Session 2는 ROLLBACK 되어 GRADE 값이 A이지만 SESSION 1은 B로 작업을 이어갑니다.
    아직 COMMIT 되지 않은 Grade가 B 라는 결과를 확인했습니다.
    Grade 를 A → B로 변경하였습니다.

  2. Non-Reapeatable Read
    트랜잭션 내에서 읽은 데이터가 트랜잭션이 종료되기 전에 다른 트랜잭션에서 변경되어 다시 읽었을 때 다른 값을 읽는 현상입니다.
    Non-Repeatable Read

    위의 예시를 보면 Session1 에서 READ COMMITTED 격리 수준으로 TB_N 테이블의 NO = 1 일 때 데이터를 조회하면 GRADE가 A인 것을 확인할 수 있습니다.
    Session 2에서 GRADE가 A인 것을 B로 변경 한 뒤 COMMIT 을 수행하고 Session1을 다시 조회하였더니 GRADE가 B로 바뀐 것을 확인할 수 있습니다.


  3. Phantom Read
    트랜잭션 내에서 읽은 데이터가 트랜잭션이 종료되기 전에 다른 트랜잭션에서 데이터를 삽입 또는 삭제하여 다시 읽었을 때 결과가 달라지는 현상입니다.
    Phantom Read

    Session1에서 READ COMMITTED 격리 수준으로 TB_P 테이블을 조회했을 때 3건의 데이터가 조회되는 것을 확인할 수 있습니다.즉, 처음에 조회한 결과값에 존재하지 않았던 ghost 레코드가 발생하였습니다.
    Session2에서 같은 테이블에 데이터를 데이터를 INSERT 한 뒤 Session1에서 다시 조회하였더니 1건의 데이터가 추가된 것을 확인할 수 있습니다.

 

격리 수준 종류

격리 수준은

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE
  • SNAPSHOT

이렇게 있습니다.

격리 수준은 잠금에 의해 구현되며, 지정한 수준에 따라서 잠금 수준이 다르게 적용됩니다.

 

  1. READ UNCOMMITTED
    데이터가 수정되었지만 아직 COMMIT 되지 않은 데이터를 읽을 수 있도록 지정하는 격리수준입니다.
    데이터 조회 시 KEY에 공유 잠금을 요청하지 않습니다.
    READ UNCOMMITTED

    → Session56에서 GRADE 값을 C로 변경 후 Commit 을 진행하지 않았는데COMMIT 되지 않은 데이터를 읽는 Dirty Read가 발생한 것입니다.
    Session 57에서 READ UNCOMMITTED 격리 수준으로 해당 테이블을 조회했을 때 GRADE 값이 C로 변경된 것을 확인할 수 있습니다.


  2. (A) READ COMMITTED
    다른 트랜잭션에 의해 수정되었지만 COMMIT 되지 않은 데이터를 읽을 수 없도록 지정하는 격리 수준으로 COMMIT된 데이터만 읽도록 허용하는 기본 격리 수준입니다.따라서 Dirty Read가 방지 되지만 Non-Repeatable Read, Phantom Read는 발생합니다.
    데이터 조회 시 공유 잠금을 획득하며 조회가 끝나면 반환합니다.
    (A) READ COMMITTED

    Session 57을 보면 READ COMMITTED 격리 수준으로 테이블을 조회하였습니다.트랜잭션이 종료되지 않은 상태에서 Session57에서 테이블을 조회하면 대기가 발생하고
    Session 56에서 COMMIT 하게 되면 베타 잠금을 반환하고 대기 중이던 Session57이 공유 잠금을 획득하면서 결과가 조회되는 것을 확인할 수 있습니다.
    Session 56을 보면 GRADE 데이터를 C로 변경 후 커밋은 진행하지 않았습니다.

  3. (B) READ COMMITTED_SNAPSHOT
    READ_COMMITTED_SNAPSHOT 이 ON으로 설정되어 있으면 데이터베이스 엔진은 행 버전 관리를 사용하여 데이터 일관성을 제공합니다.
    트랜잭션이 시작되는 시점에 스냅샷이 생성되기 때문에 키 공유 잠금 없이도 일관성 있게 데이터를 조회할 수 있습니다. 즉, 공유 잠금 요청 없이 커밋된 데이터를 읽을 수 있습니다.
    READ COMMITTED_SNAPSHOT은 ALTER 구문을 통해 데이터베이스를 변경해줘야합니다.
ALTER DATABASE {데이터베이스명} SET READ_COMMITTED_SNAPSHOT ON

READ_COMMITTED_SNAPSHOT

Session57에서 READ_COMMITTED_SNAPSHOT을 활성화시킨 뒤 READ COMMITTED 격리 수준으로 3이상 5이하 데이터를 조회했습니다. Session56에서 no 가 5인 데이터의 GRADE를 A로 업데이트한 후 동일하게 데이터를 조회하면 변경된 값으로 조회되는 것을 확인할 수 있습니다.

다시 Session57에서 동일하게 조회하면 Session56에서 잠금에 대해 공유 잠금을 요청하지 않아, 처음 결과와 동일한 것을 확인할 수 있습니다.

Session56에서 COMMIT을 하여 트랜잭션을 완료하면 Session57에서는 변경된 데이터가 반영되는 것을 확인할 수 있습니다.

즉, 구문이 실행될 때 스냅샷을 찍기 때문에 업데이트가 반영된 것입니다.

반응형

'Database > MS-SQL' 카테고리의 다른 글

부속 질의 ( 스칼라 서브쿼리, 인라인 뷰)  (0) 2024.09.09
부속 질의 ( 서브 쿼리 )  (1) 2024.09.02
내장함수 (2) | Null 함수  (0) 2024.08.26
내장 함수  (0) 2024.08.15
[MS-SQL] 인덱스 (INDEX)란?  (4) 2024.08.12