SQL) 데이터베이스 아키텍쳐 Ⅲ

jinsung·2025년 11월 26일

SQL

목록 보기
10/46
post-thumbnail

6. 문장수준 읽기 일관성

데이터베이스에서 읽기 일관성(Read Consistency)이란?

쿼리를 실행하는 동안, 해당 쿼리가 보는 데이터는 “논리적으로 일관된 하나의 시점”이어야 한다는 원칙을 말한다
즉, 내가 SELECT를 실행했을 때 조회되는 데이터는 쿼리가 시작된 시점의 상태로 고정되고,그 이후 다른 트랜잭션이 데이터를 변경하더라도 내 SELECT 결과에는 반영되지 않아야함

단일 SQL문이나 트랜잭션 내에서 일련의 SQL문이 차례로 수행되는 도중에 다른 트랜잭션에 의해 데이터가 변경, 추가, 삭제된다면 일관성 없는 결과집합을 리턴하거나 값을 잘못 갱신하는 문제가 발생할 수 있다. 이런 현상들을 방지하고 읽기 일관성을 보장하기 위해 DBMS마다 트랜잭션 읽기 일관성, 문장수준 읽기 일관성등을 제공한다.


1) 문장 수준 읽기 일관성이란?

단일 SQL문이 수행되는 도중에 다른 트랜잭션에 의해 데이터의 추가, 변경, 삭제가 일어나더라도 일관성있는 결과집합을 리턴하는 것을 말함

  • Dirty Read 허용하면 읽기 일관성 보장 x
    -> 다른 DBMS들은 로우 Lock을 사용해 Dirty Read 방지

  • 오라클은 Lock을 사용하지 않고 Undo 세그먼트에 저장해 둔 Undo 데이터를 활용하므로 완벽한 문장수준 읽기 일관성을 보장

다른 DBMS들은 Lock을 사용해 읽기 일관성을 구현하는데, 기본 트랜잭션 고립화 수준(lv1, Read Commited)에서는 값을 읽는 순간에만 Shared Lock을 걸었다가 다음 레코드를 이동할 때 Lock 해제
-> Shared Lock이 해제되기 때문에 이미 읽고 지나간 레코드를 다른 트랜잭션이 변경할 수 있게 되고, 이 때문에 문장수준 읽기 일관성이 보장되지 않는 문제가 생긴다
-> 트랜잭션 고립화 수준을 상향 조정하면 Lock이 발생하는 범위가 넓어지고 더 오래 유지되기 때문에 동시성 저하를 초래함 + 교착상태 발생 가능성 높아짐

  • 오라클을 사용하면 위와 같은 트랜잭션 고립화 수준의 문제에 상황을 우려하지 않아도 됨
    -> 오라클은 높은 수준의 동시성을 유지하면서도 완벽한 문장수준 읽기 일관성을 보장

(2) Consistent 모드 블록 읽기

  • Current 블록 : 디스크로부터 읽혀진 후(데이터를 찾아간 바로 그 시점의 최종 값) 사용자의 갱신사항이 반영된 최종 상태의 원본 블록

  • Consistent 블록 : 쿼리가 시작된 시점을 기준으로 데이터를 읽음

-> CR 블록은 Current 블록의 복사본임, CR블록은 여러개 가능 Current 블록은 단 하나

오라클의 MVCC 모델
=> 오라클은 Current 블록을 CR Copy 블록으로 복사하여 읽기 일관성을 지원함
데이터를 다중 버전 상태로 유지하고 있어 Commit전에 Undo 영역에 유지하고 있기 때문


그러면 오라클에서 Consistent 모드로 데이터를 읽을 떄, 쿼리 시작 시점과 블록의 마지막 변경 시점을 어떻게 확인할까?

1) 쿼리 시작 시점

오라클은 SCN(System Commit Number)이라고 하는 시간정보를 이용해 데이터베이스의 일관성 있는 상태를 식별, 쿼리 SCN이라 부름

  • 사용자가 커밋할 때 SCN += 1
  • 커밋이 없을 때는 오라클 백그라운드에서 조금씩 증가
  • 읽기 일관성과 동시성 제어를 위해 사용
  • 생성된 Redo 로그 정보의 순서를 식별
  • 데이터 복구를 위해 사용

2) 블록 마지막 변경 시점

오라클은 블록이 마지막으로 변경된 시점 정보를 식별하기 위해 모든 블록 헤더에 SCN(System Change Number) 정보를 관리하는데 블록 SCN이라 부름


3) Consistent 모드 읽기의 세부원리

Consistent 모드에서 데이터를 읽을 때 쿼리 SCN을 들고다니면서 블록 SCN과 비교해 읽을 수 있는지 판단함

  • 데이터 갱신은 항상 Current 블록만 가능

1. Current 블록 SCN <= 쿼리 SCN이고, committed 상태

  • 블록 SCN이 쿼리 SCN보다 작거나 같은 블록만 읽을 수 있음

2. Current 블록 SNC > 쿼리 SCN이고, committed 상태

  • Current 블록이 committed 상태지만 블록 SCN이 쿼리 SCN보다 크다면 쿼리가 시작된 이후 해당 블록에 변경이 가해지고 커밋된 것을 의미

1. Current 블록의 블록 SCN이 쿼리 SCN보다 크면 CR Copy 블록을 먼저 생성 (CR Cloning)

2. CR 블록은 쿼리 SCN 보다 작은 블록 SCN의 과거 버전으로 되돌림

  • 블록 SCN <= 쿼리 SCN 조건을 만족할 때까지 과거 버전으로 되돌리기를 반복

  • 완성된 CR 블록은, 블록 SCN이 쿼리 SCN보다 작거나 같으면서 커밋되지 않은 내용은 전혀 포함하지 않은 상태가 됨

3. Current 블록이 Active 상태, 즉 갱신이 진행 중인 것으로 표시 돼 있을 때

  • 쿼리 SCN 이후에 커밋된 블록으로 확인되거나, 커밋되지 않아 아직 클린아웃 할 수 없다면 CR Copy를 만들어 쿼리 SCN보다 낮은 마지막 committed 상태로 되돌린 후 읽어야 한다

7. Consistent vs Current 모드 읽기

(1) Consistent 모드 읽기와 Current 모드 읽기의 차이점

1. Consistent 모드 읽기

  • SCN 확인 과정을 거치며 쿼리가 시작된 시점을 기준으로 일관성 있는 상태로 액세스 하는 것
  • 쿼리를 읽는 시간과 관계없이 항상 쿼리가 시작된 시점의 데이터를 가져온다
  • SQL 트레이스의 query 항목
  • AutoTrace의 consistent gets 항목
  • 위 항목은 대부분 SELECT문에서 읽은 블록이고, CR블록을 생성하려고 Undo 세그먼트로부터 읽어들이는 블록 수까지 더해진다

2. Current 모드 읽기

  • SQL문이 시작된 시점이 아니라 데이터를 찾아간 바로 그 시점의 최종 값을 읽으려고 블록을 액세스 하는 것
  • 블록 SCN이 쿼리 SCN보다 높고 낮음을 따지지 않고, 그 시점에 이미 커밋된 값이라면 그대로 받아들이고 읽음
  • SQL 트레이스의 current 항목
  • AutoTrace의 db block gets 항목

    이 블록들이 나타나는 상황들

    • DML문을 수행할 때 주로 나타난다
    • SELECT FOR UPDATE문을 수행할 때 Current 모드 읽기 보통 사용
    • 8i 이전 FULL SCAN SELECT문 -> Current 모드 읽기
      9i 이후 FULL SCAN -> Consistent 모드 읽기
    • 디스크 소트가 필요할 정도로 대량의 데이터를 정렬 할 때 나타난다

(2) Consistent 모드 갱신 시 생기는 현상

Consistent 모드는 쿼리 시작 시점을 기준으로 값을 읽기 때문에 이 값을 기준으로 갱신하면 Lost Update가 발생하는 결과를 초래한다.
이런 Lost Update 문제를 회피하려면 갱신 작업만큼은 Current 모드를 사용해야 한다.


(3) Current 모드로 갱신 시 생기는 현상

예를 들면, UPDATE가 이미 진행된 블록에 INSERT된 레코드는 갱신 대상에서 제외되고, 아직 UPDATE 되지 않은 블록에 INSERT된 레코드는 갱신 대상에 포함된다.
또 다른 예로는, "DELETE FROM LOGG" 문장이 수행되는 도중에 다른 트랜잭션에 의해 새로 추가된 로그 데이터까지 지워질 수 있다.


요약하자면?

  1. SELECT문은 Consistent 모드로 읽는다
  2. INSERT, UPDATE, DELETE, MERGE 등의 DML은 Current 모드로 읽고 쓴다
  3. 다만, 갱신할 대상 레코드를 식별하는 작업만큼은 Consistent 모드로 이루어진다
profile
Data Engineer

0개의 댓글