RAC와 몰락

Big Picture

  • RAC의 런-타임 메커니즘을 강조

그림 8-1 개략적인 RAC 시스템

  • 네트워크
    • public 네트워크: 사용자 프로그램의 접속
    • private 네트워크: 인스터스간의 통신과 SGA의 일관성을 유지하기 위해 인스턴스간에 사용
      • 최대한 낮은 대기시간( lowest latency )을 보장할 필요가 있다.
  • 스토리지 : 모든 인스턴스는 모든 스토리지를 액세스 할 수 있어야만 한다.
  • 장비간의 통신 실패를 제어하는 메커니즘으로써 사용되는 특별한 디스크가 존재한다.
    • 특히, RAC의 각 노드간의 물리적인 거의가 먼 경우에 RAC를 매우 정교하게 다루기를 원한다면,
      이런한 디스크가 최소한 3개를 필요하면, 이상적으로는 물리적으로 분리된 곳에 위치하는 것이 바람직하다.
  • 운영 체제와 오라클 인스턴스 사이에서 수행되는 소프트웨어( 클러스터 서비스 )의 몇 개의 계층은 장비간의 통신을 보장하는 역할을 한다.
  • 오라클의 클러스터 소프트웨어에 의한 설정되는 "virtual 네트워크"가 존재하며, public 네트워크 위에서 동작한다.
    • 실제로 virtual 네트워크는 클라이언트 프로그램이 오라클 인스턴스와 통신하기 위해 사용된다.
      이것은 오라클 데이터베이스 장비와 장애를 매우 빠르게 클라이언트에게 전달하는 것을 가능하게 하며,
      클리이언트는 짧은 시간 내에 정상적인 장비로 접속할 수 있다.
  • 만일 오라클이 선호하는 설치방식을 사용한다면, 각 장비에 두 개의 인스턴스가 기동된다.
    • 데이터 베이스 인스턴스( SID )
    • 스토리지 관리용 ( ASM )
      • 장비당 하나만 필요하다. 실질적으로 ASM 은 운영체제와 데이터베이스 인스터스 사이의 계층에서 logical 볼륨 매니저처럼 동작한다.

VIRTUAL IP 주소 및 SCAN

  • 클러스터 서비스가 기동되자 마자 real IP 주소 위에 virtual IP ( VIP )주소를 입력한 후, 장비간의 통신은 VIP를 이용하도록 전환된다.

Virtual IP와 real IP 차이점

  • real IP : 논리적으로 하드웨어의 특정 부분( 기술적으로 네트워크 카드의 MAC 주소 )과 연결
  • VIP : 소프트웨어에 의해 제어되고 하드웨어와 연관된 부분도 동적으로 변경가능

장애

  • 1. 클라인어트 프로그램이 real IP로 접속한 데이터베이스 장비에 장애가 발생
  • 2. 클라이언트 프로그램은 서버 장비의 장애 발생에 대한 응답을 오랜 시간( 10 ~ 100 여초 ) 대기 할 수 있다.
  • 3. 오라클은 virtual IP를 사용하므로, 장비 장애가 발생할 때, 인스턴스 중의 하나가 장애 사실을 매우 바르게 감지하고,
  • 4. 현재 요청을 처리하기 위해 장애가 발생한 장비의 virtual IP를 가져오게 된다.
  • 5. 이러한 재구성은 장애가 발생한 VIP에 대해서는 더 이상의 접속을 중단시킨다. ( 장비와 인스턴스가 복구된 후 기동 전까지 )
  • 6. 이것은 클라이언트가 접속하려는 인스턴스에 장애가 발생해도, 오랜 시간 대기하지 않는다는 것은 의미한다.

SCAN ( Single Client Aceess Name )

  • 11.2는 그리드 인프라스트럭처의 한 부분
  • SCAN을 사용하기 위한 사전 작업으로 새로운 DNS( Domain Name Service ) 항목을 설정하거나,
    오라클의 GNS( Grid Naming Service )를 사용하기 위한 DNS의 서브항목을 설정하기 위해 시스템 관리자 권한을 얻어야 한다.
  • 설정이 완료되면, 모든 클라이언트 프로그램은 SCAN을 통해 시스템을 참조할 수 있으며,
    시스템을 다른 하드웨어로 이전하거나, 노드를 추가 또는 제거할 때도 클라이언트 설정을 재구성할 필요가 없게 된다.

다양한 안전장치

  • 네트워크 장애로 인해 다른 인스턴스들과 상호 통신할 수 없을 때 어떤 일이 발생할까?
    적절한 안전장치가 없다면 각 인스턴스내의 변경사항들이 중복되어 써지게 될 것이다.( 이로 인해 데이터 불일치 현상이 발생한다 )
    • 이런한 위협은 두 개의 계층에서 발생할 수 있다.
      • 첫 번째는 장비간의 통신 단절
      • 두 번째는 오라클 인스턴스 간의 통신 단절

장비 레벨에서의 방어

  • 각 장바의 클러스터 서비스는 네트워크를 통해 상호간의 통신 수행 및 voting 디스크를 통해서도 상호간의 통신ㅇ르 수행한다.

통신 문제를 처리할 수 있는 몇 가지 옵션

  • 1. 매초마다, 모든 장바는 voting 디스크에 기록한다.
    • 디스크 내에는 장비당 하나의 파일( 1나의 블록으로 구성 )이 존재하며, 각 장비는 단순히 블록 내의 카운터를 증가한다.
      만일 파일에 기록할 수 없다면, 해당 장비는 스스로를 클러스터로부터 분리한 후 클러스터를 보호하기 위해
      재 기동될 수 있다.( 비정상적으로 종료되고 다른 인스턴스중 하나가 해당 인스턴스에 대한 복구를 수행한다. )
  • 각 장비는 자신의 블록( voting 디스크 )에 기록 작업을 수행한다.
  • 클러스터 내의 다른 모든 장비들이 기록 작업ㅇ르 수행했는지 체크한다.
    • 따라서 가장 최근에 자신의 블록을 변경하지 못한 장비를 발견할 수 있다.
      • 문제를 발겨한 장비는 문제가 있는 장비를 종료시킬 수 있다.
  • 모든 장비들은 블록( voting 디스크)에 기록작업을 수행할 수 있지만, 네트워크 문제로 인해 장비 상호간의 통신이 단절되는 경우도 존재한다
    • 한 장비는 voting 디스크에 대한 모든 기록을 제한하고(?), 통신 가능한 장비의 수를 계산한다.
      만일 해당 장비가 속한 그룹이 전체 장바의 반 이상을 포함하거나, 만일 장비의 수가 동일하다면,
      가장 작은 클러스트 id를 가진 장비를 포함한 그룹이 나머지 장비들을 클러스터로부터 분리하고 그들을 재 기동하게 된다.
      • 만일 해당 장비가 필요한 정족수( 이로 인핸 voting 디스크를 "quorum(정족수)"디스크라고도 한다 )를 얻지 못하면,
        스스로를 클러스터로부터 분리한다.

오라클 레벨에서의 방어

  • 각 인스턴스가 기동되면 다른 인스턴스들에게 시작 사실을 알린다.
    • 모든 인스턴스는 살아있는 다른 인스턴스들의 수를 알수 있다.
  • 인스턴스가 종료되면, 다른 인스턴스들에게 종료 사실을 전달한다.
  • 인스턴스 그룹의 마지막 상태에 따라, 인스턴스들은 스스로를 변경된 수에 맞추어 "rebalance"한다.
    • 이 시점 이후부터, 모든 인스턴스는 다른 인스턴스들과 네트워크를 통해서 지속적으로 통신한다.( 네트워크 heartbeat 프로세스로써 LMON이 사용된다 )

LMHB( lock manager heart beat monitor )

  • 11.2
  • RAC에서의 모든 인스턴스가 자신의 CKPT 프로세스를 소유한다
    • 이에 따라 컨트롤 파일은 heartbeat 파일로써 동작할 수 있다.
  • 인스턴스가 컨트롤 파일에 더 이상 기록할수 없다는 것을 감지하면, 시스템의 안정성를 위해서 스스로 종료할 수 있다.
  • 인스턴스가 hang을 감지하면 다른 인스턴스들에게 hang 상태를 알리는 것도 가능할 것이다.
  • 한 인스턴스 ( 정족수 그룹 내에 존재하는 인스턴스인 경우 )가 다른 인스턴스를 종료시키는 것을 허용하는 코드를 포함

RAC의 핵심

고 가용성

  • 1. RAC 시스템 중의 한 노드에 장애가 발생하면, 아주 짧은 순간에 다른 노드 중의 하나가 장애가 발생한 노드의 리두를 이용하여 장애를 복구
  • 2. 노드들을 rebalance한 후에 정상적인 처리를 계속한다는 것이다.
재 기동 시간은 얼마나 중요한가? 예들 들어 10초 이내? 그리고 느리더라도 대체 장비를이용하는 것이 가능한가?
디스크 또는 네트워크 장애에 비해서 장비 장애가 얼마나 자주 발생하는가? RAC로 부터 얻게 된느 이득을 얼마나 되는가?
갈수록 복잡해지는 RAC 소프트웨어와 패치 및 업그레이드를 수행할 수 있는 인적 자원을 보유하고 있는가?
성능에 영향을 주지 않고 N개의 노드의 작업량을 N-1 개에서 처리하려면 몇개의 노드가 필요한가?

Failover

  • failover는 사용자 프로그램 관점에서는 거의 투명하게( 만일 프로그램을 재 작성하지 않는다면, 현재 수행중인 트랜잭션에는 적용되지 않지만 )이루어진다.
    • 단점 : failover 시간이 길어진다. 장비가 유휴상태이거나 사용 중이더라도 여분의 처리 능력이 있어야 한다는 것

확장성

  • 동일한 작업을 더 빨리 수행한다 - 향상된 응답시간 ( 개별적인 큰 작업을 수행한다 )
  • 동일한 시간에 동일한 작업을 여러 번 수행한다 - 향상된 처리량 ( 다수의 작은 작업을 수행한다 )

그리드

  • 하나의 대형 장비에 의존하는 것보다 저 비용의 장비들을 클러스터로 묶어서 사용하는 것은 그리드에서 유래된 개념
  • 클러스터 내에 다수의 소형 장비( 아직 어떤 오라클 인스턴스도 수행되지 않은 )가 존재한다면
    다수의 데이터베이스를 생성할 수 있으며,
    각 애플맄이션을 위해 각 장비에서 수행될 인스턴스의 수를 선택할수 있으며,
    동적으로 작업량을 재분배할 수 있다.

active/passive 모드

  • 오라클은 통신비용을 제거한 특별한 2노드 RAC 구성을 제공한다.
    • 한 인스턴스만 일하고 다른 한 인스턴스는 첫 번째 인스턴스가 장애가 날 때 까지는 (원칙적으로)아무 일도 하지 않는다. ( 라인센스가 틀린건가;; )
      • 장점 : 작은 클러스터 내에 빠른 복구를 필요로 할 경우에 사용할만한 전략

RAC 동작 원리

GRD ( Global Resource Directory )

  • GES: global enqueue service 는 이미 싱글 인스턴스에서 논의되었던 일반적인 락킹을 다룬다.
    • 한 인스턴스에서 모드 3(row-share)으로 테이블에 락을 획드했다면, 다른 인스턴스에서 모드 6( exclusive )으로 테이블에 락을 설정할 수 없다.
      • 백그라운드 프로세스 : LCK0, LMD, LMON
  • GCS: global cache service는 블록 관리 ( 또는, 캐시 일관성 )를 다룬다.
    • 한 인스턴스가 블록의 복사본을 변경했다면, 다른 인스턴스는 해당 복사본( bufffered copy )을 변경할 수 없다.
      • 복사본 중 하나만이 디스크로 저장되기 때문, 따리서 상호간의 수행하는 일과 단하나의 current 복사본만을 유지하는 메커니즘이 필요하다.
        • 백그라운드 프로세스 : LMSn ( 다른 인스턴스의 SGA를 직접 읽지 않고, 대부분 LMSn과 LMD를 통해 메시지를 전달한다. )

리소스의 락킹 및 모든 인스턴스에서 리소스를 명확히 확인 할 수 잇는 메커니즘

  • v$dlm_ress : distribute lock manager resources
  • v$ges_enqueue : global enqueues services enqueues ( 이전버전 : v$dlm_locks )
  • GDS

v$sgastat 및 v$resource_limit

  • 메모리 구조의 크기를 확인할 수 있다.

22:52:55 SYSTEM @ ec_test> SELECT RESOURCE_NAME, CURRENT_UTILIZATION, MAX_UTILIZATION
22:53:24   2    FROM V$RESOURCE_LIMIT
22:53:37   3  WHERE RESOURCE_NAME LIKE '%g_s%'
22:53:52   4  order by 1
22:54:00   5  ;

RESOURCE_NAME                  CURRENT_UTILIZATION MAX_UTILIZATION
------------------------------ ------------------- ---------------
gcs_resources                               321051          467528
gcs_shadows                                 168214          188362
ges_big_msgs                                    24             586
ges_cache_ress                               19779           23526
ges_locks                                     9228           41217
ges_procs                                      404             636
ges_reg_msgs                                   255             701
ges_ress                                     46737          192394
ges_rsv_msgs                                     0               0

9 개의 행이 선택되었습니다.

22:54:02 SYSTEM @ ec_test> select *
22:54:22   2    from v$sgastat
22:54:31   3  where name like '%gcs%'
22:54:39   4  or name like '%ges%'
22:54:47   5  order by name
22:54:51   6  ;

POOL         NAME                            BYTES
------------ -------------------------- ----------
shared pool  KSXR pending messages que      861984
shared pool  gcs commit sga state           106504
shared pool  gcs dynamic r                 8677760
shared pool  gcs opaque in                    8208
shared pool  gcs procsss descriptor          42832
shared pool  gcs res hash bucket           4194304
shared pool  gcs res latch table             25600
shared pool  gcs resources                88575408
shared pool  gcs shadows                  61321440
shared pool  ges big msg buffers          15090728
shared pool  ges deadlock xid freelist       11264
shared pool  ges deadlock xid hash tab       17800
shared pool  ges enqueues                 84225136
shared pool  ges process array             6081520
shared pool  ges process descriptor          21416
shared pool  ges process hash table         176000
shared pool  ges regular msg buffers      10825208
shared pool  ges reserved msg buffers      8440008
shared pool  ges resource                 73898392
shared pool  ges resource hash seq tab      131072
shared pool  ges resource hash table       5767168
shared pool  ges shared global area          33944
shared pool  messages                       960000

23 개의 행이 선택되었습니다.

22:54:52 SYSTEM @ ec_test>

  • v$sgastat : GES enqueues
  • v$resource_limt : GES_locks
  • GCS에 대한 enqueue( 또는 lock )는 보고되지 않는다는 것을 알 수 있다.
  • GCS shadows : 오라클은 캐시 처리와 일반적인 enqueue 처리를 분리
    • 캐시 처리를 위한 수행 빈도수가 휠씬 많고, 인터커네터를 통해 전송되는 패킷의 크기도 훨씬 크기 때문이다.
      • global cache resources를 위한 분리적인 구조를 갖는다. ( 물론, 분리된 구조를 갖는 다른 이유도 존재한다 )
        • 즉, 인스턴스 장애가 발생할 때, 장애가 발생한 인스턴스가 획득한 일반적인 락,
          또는 딕셔너리 캐시, 똔느 라이브러리 캐시 항목에 대해서 걱정할 필요가 없다는 것이다.
          또한, 캐시 내에 존재하는 데이터 블록과 이들 블록의 상태를 확인하기 위해서
          GCS는 블록의 위치와 상태를 보다 정교하게 추적해야 하고,
          이를 위한 별도의 구조가 필요하다.
          따라서 오라클은 global cache resources를 위한 분리된 구조를 제공한다.
  • 이들 뷰는 gcs RESOURCES 와 gcs SHADOWS를 제공한다.
    • 오라클은 리소스를 제어( 또는 mastering ) 하기 위한 권한을 클러스터 내에 모든 인스
      턴스에게 동등하게 공유한다.
      • 하지만 현재 리소스를 사용하는 모든 다른 인스턴스( master를 제외한 )는 master
        리소스로부터 중요한 정보의 일부를 포함하는 shadow 리소스를 유지한다.
        그리고 캐시 리소스의 경우에는 이를 확인할 수 있는 명확한 뷰를 가진다.

Master 및 Shadow

  • 근본적으로, 해시 함소를 사용하여 임의로 분배하는 것에 기반을 둔다.
    • 만일 한 인스턴스에서 특정 인스턴스의 글로벌상태를 확인하기를 원한다면,
    • 리소스 식별자를 이용하여 해시 값을 계산하 후 해당 리소스의 마스터 인스턴스를 찾는다.
      • 예를 들어, 테이블 xyz에 락을 설정하기 원한다면, 해당 인스턴스는 테이블의 오브젝트
        아이디를 이용하여 몇 가지 연산을 수행한 후 해당 테이블의 마스터 TM 리소스를
        소유한 노드를 확인할 수 있다.
        • 그런 후에 다른 인스턴스들이 호환되지 않는 모드로 해당 리소스에 락을 설정했는지의 여부를 확인한다.

REMASTERING

  • 필자님 왈 : 오라클이 산술적인 연산을 수행함으로써 오브젝트의 마스터 리소스를 찾는다고 언급
    • 이러한 동작원리의 원칙은 오라클 버전에 따라 다르고, 데이터 블록에 대해서 특별한 경우도 존재한다.
  • 만일 DATA OBJECTS가 다른 인스턴스들 보다 특정 인스턴스에서 더 많이 사용된다는 것을
    감지하면, 일반적인 주소 기반의 연산을 수행하지 않고, 해당 인스턴스를 해당 오브젝트의
    모든 블록에 대한리소스 마스터로 정한다 ( 버전에 따라 이 절차는 세 단계를 통해 진화 되었다. )
    • A : 전혀 동작하지 않음
    • B : 파일 레벨에서 동작
    • C :오브젝트( 데이터 세그먼트 ) 레벨에서 동작
  • 오브젝트의 맵 : 데이터 오브젝트의 수는 데이터베이스 내의 블록 수와 비교하면 상대적으로 작은 경향이 있으므로,
    각 인스턴스는 모든 데이터 오브젝틔 맵을 유지하는 것이 가능하다.
    • 리스토 마스터에 대한 정보 : 개별블록에 대한 마스터를 찾기 위한 산술 연산을 수행하기 전에 데이터 오브젝트 마스터링을 확인하기 위한 용도
      • 알고리즘 핵심 : 동적으로 오브젝트를 리마스터 한다는 것
        • 단점 : 오브젝트에 대한 기존의 리소스 마스터를 새로운 인스턴스로 이동하기 위해, 아주 짧은 순간 GRD를 동결시킬 필요가 있다.
          처리 속송에 따라 몇 개의 오브젝트는 상당히 정기적으로 리마스터 될 수 도 있다.( Statspack, AWR 확인 가능 )

TM 리소스 확인



20:13:31 SYSTEM @ EC_TEST> SELECT OBJECT_NAME, OBJECT_ID, '0x'||TO_CHAR( OBJECT_ID, 'FMxxxxxxxx' ) "16진수"
20:13:32   2    FROM DBA_OBJECTS
20:13:32   3   WHERE OBJECT_NAME = 'WRH$_LATCH'
20:13:32   4     AND OBJECT_TYPE = 'TABLE';

OBJECT_NAME                                                                                                               OBJECT_ID 16진수
-------------------------------------------------------------------------------------------------------------------------------- ---------- -----------
WRH$_LATCH                                                                                                                     6241 0x1861

20:13:34 SYSTEM @ EC_TEST>   select *
20:13:40   2       from gv$dlm_ress
20:13:40   3      where 1 = 1
20:13:40   4        and RESOURCE_NAME like '%0x1861%'
20:13:40   5        and RESOURCE_NAME like '%TM%';

   INST_ID RESP             RESOURCE_NAME                  ON_CONVERT_Q ON_GRANT_Q PERSISTENT_RES MASTER_NODE NEXT_CVT_ VALUE_BLK_STATE                  VALUE_BLK
---------- ---------------- ------------------------------ ------------ ---------- -------------- ----------- --------- -------------------------------- ---------------------------------------------------------
         2 0700010110B461E8 [0x1861][0x0],[TM][ext 0x0,0x0            0          1              0           1 KJUSERNL  KJUSERVS_NOVALUE                 0x00000000000000000000000000000000 .
         1 070001010FEA0FE0 [0x1861][0x0],[TM][ext 0x0,0x0            0          0              0           1 KJUSERNL  KJUSERVS_NOVALUE                 0x00000000000000000000000000000000 .

20:13:43 SYSTEM @ EC_TEST>
20:21:01 SYSTEM @ EC_TEST> SELECT inst_id
20:21:03   2       , handle
20:21:03   3       , grant_level
20:21:03   4       , request_level
20:21:03   5       , resource_name1
20:21:03   6       , resource_name2
20:21:03   7       , state
20:21:03   8       , owner_node
20:21:03   9    FROM gv$ges_enqueue
20:21:03  10   WHERE 1 = 1
20:21:03  11     AND resource_name1 LIKE '%0x1861%'
20:21:03  12     AND resource_name1 LIKE '%TM%';

   INST_ID HANDLE           GRANT_LEV REQUEST_L RESOURCE_NAME1                 RESOURCE_NAME2              STATE                                                               OWNER_NODE
---------- ---------------- --------- --------- ------------------------------ ------------------------------ ---------------------------------------------------------------- ----------
         2 0700010134AF1090 KJUSERCW  KJUSERCW  [0x1861][0x0],[TM][ext 0x0,0x0 6241,0,TM                      GRANTED                                                                   0

20:21:11 SYSTEM @ EC_TEST>



  • v$ : 싱글 인스턴스 내의 동적 성능 뷰 ( 싱글 인스턴스 )
    • gv$로 시작하는 글로벌 뷰의 부분집합
      • 조회 : 다른 노드들에 병렬 쿼리 슬레이브 프로세스를 생성한다. ( PZ99 )
        • parallel_max_servers 를 0으로 병렬 쿼리를 비활성화 해도 RAC에서 이들 슬레이브는 여전히 동작한다.
  • MASTER_NODE : 1
    • 마스터 노드는 리소스에 대한 마스터임에도 불고하고 리소스에 대한 enqueue를 소유하지 않았다.
      • KJUSERCW( concurrent write ) == v$lock 의 row-exclusive 동등, 이들 구조를 볼 수 있는 뷰 또는 x$ 구조가 제공되지는 않지만,
        해시 테이블, 포인트 및 링크드 리스트는 싱글 인스턴스 enqueue 를 위해 동작하는 것과 동일한 방식으로 글로벌 enqueue 를 위해 제공된다.

shadow 리소스

  • shadow 리소스에 등록된 enqueue는 shadow 노드에서만 볼 수있다.
  • QQ 리소스 : 히스토그램과 관련된 딕셔너리 캐시 유형의 하나이다.


17:46:30 SYSTEM @ EC_TEST>   SELECT inst_id
17:46:31   2         , handle
17:46:31   3         , grant_level
17:46:31   4         , request_level
17:46:31   5         , resource_name1
17:46:31   6         , resource_name2
17:46:31   7         , state
17:46:31   8         , owner_node
17:46:31   9      FROM gv$ges_enqueue
17:46:31  10     WHERE 1 = 1
17:46:31  11       AND inst_id IS NULL;

선택된 레코드가 없습니다.

17:46:35 SYSTEM @ EC_TEST>   SELECT inst_id
17:46:50   2         , handle
17:46:50   3         , grant_level
17:46:50   4         , request_level
17:46:50   5         , resource_name1
17:46:50   6         , resource_name2
17:46:50   7         , state
17:46:50   8         , owner_node
17:46:50   9      FROM gv$ges_enqueue
17:46:50  10     WHERE 1 = 1
17:46:50  11  --     AND inst_id IS NULL
17:46:50  12       AND resource_name1 = '[0xb2ce6fd2][0xfc5c0098],[QQ]['
17:46:50  13  ;

   INST_ID HANDLE           GRANT_LEV REQUEST_L RESOURCE_NAME1                 RESOURCE_NAME2              STATE                                                               OWNER_NODE
---------- ---------------- --------- --------- ------------------------------ ------------------------------ ---------------------------------------------------------------- ----------
         2 070001010E25CCC0 KJUSERPR  KJUSERPR  [0xb2ce6fd2][0xfc5c0098],[QQ][ -1295093806,-61079400,QQ       GRANTED                                                                   1
         1 070001010B96F0B0 KJUSERPR  KJUSERPR  [0xb2ce6fd2][0xfc5c0098],[QQ][ -1295093806,-61079400,QQ       GRANTED                                                                   0
         1 070001013315A750 KJUSERPR  KJUSERPR  [0xb2ce6fd2][0xfc5c0098],[QQ][ -1295093806,-61079400,QQ       GRANTED                                                                   1

17:46:54 SYSTEM @ EC_TEST>


  • GRANT_LEVEL : KJUSERPR ( PROTECTED READ를 의미하며, V$LOCK 뷰의 모드 4 )
  • 마스터 노드 : OWNER_NODE에 많이 등록된 노드가 마스터로 보는건가 ( ? ) : 1
  • shadow 노드 : 위 논리가 맞다면 2

GCS와 GES



18:09:05 SYSTEM @ EC_TEST> SELECT   -- resource
18:09:05   2           SUBSTR (resource_name, INSTR (resource_name, ',') + 2, 2)
18:09:05   3         , COUNT (*)
18:09:05   4      FROM v$dlm_ress
18:09:05   5  GROUP BY SUBSTR (resource_name, INSTR (resource_name, ',') + 2, 2)
18:09:05   6  ORDER BY 2 DESC;

SUBS   COUNT(*)
---- ----------
BL       163185
QQ         9458  -- dictionary cache, histograms
QI         5844  -- dictionary cache, objects
TM         5372
HW         4947
QD         2748
QC         2651  -- dictionary cache, segments
US         1867
NB         1850
LB         1793
TA         1753
MR          510
FB          301
KO          259
DF          255
CI          184
QG          129
IV          127
QK          124
QR          100
...


18:13:15 SYSTEM @ EC_TEST> SELECT   -- enqueues
18:13:17   2           SUBSTR (resource_name2, -2), grant_level, request_level, count(*) cnt
18:13:17   3      FROM v$ges_enqueue
18:13:17   4  GROUP BY SUBSTR (resource_name2, -2), grant_level, request_level
18:13:17   5  ORDER BY cnt DESC;

SUBS GRANT_LEV REQUEST_L        CNT
---- --------- --------- ----------
BL   KJUSERPR  KJUSERNL      390489
BL   KJUSEREX  KJUSERNL       93769
QQ   KJUSERPR  KJUSERPR        8534
QI   KJUSERPR  KJUSERPR        5832
QD   KJUSERPR  KJUSERPR        4143
QC   KJUSERPR  KJUSERPR        2560
TA   KJUSEREX  KJUSEREX        1501
MR   KJUSERPR  KJUSERPR         764
DF   KJUSERPR  KJUSERPR         382
AE   KJUSERPR  KJUSERPR         286
VV   KJUSERPR  KJUSERPR         283
TA   KJUSERNL  KJUSERNL         250
TM   KJUSERCW  KJUSERCW         197
CI   KJUSERNL  KJUSERNL         193
QK   KJUSERPR  KJUSERPR         145
NB   KJUSERPR  KJUSERPR         143
QG   KJUSERPR  KJUSERPR         129
LB   KJUSERPR  KJUSERPR         129
KO   KJUSERNL  KJUSERNL         123
...


  • Qx 리소스가 높을때 : 다수의 파타션을 가진 파티션 테이블이 존재하고, 히스토 그램이 많을수록 큰 값을 나타낸다.
  • BL 리소스 : 하나의 블록을 관리한다.( global temporary 테이블과 read-only 테이블스페이스는 예외 )
    • 하나의 블럭의 다수의 블럭을 관리한다.
    • 블럭이 인스턴스 중 하나의 버퍼캐시에 적재되면 관련된 BL 리소스가 존재하게 된다.
      • 이론상 : 전 시스템에 걸쳐 존재하는 마스터 BL 리소스의 개수는 전 시스템의 버퍼 수와 동일 할 수 있다.
        • 하지만 이는 전시스템의 모든 버퍼가 서로 다른 블록을 적재하는 경우에만 가능한 일
        • 실제로, 각 인스턴스 내에는 하나의 블록에 대한 여러 개의 복사본을 가지고 있는 경향이 있으므로,
          마스터 BL 리소스의 개수는 버퍼의 전체 수보다 휠씬 적을 것이다.

Qx 리소스와 BL 리소스의 차이점

  • 1 : 딕셔너리 캐시( Qx )는 매우 안정적인 경향이 있다.
    • 데이터베이스 기동 후 몇 분내에 딕셔너리 캐시에 필요한 대부분의 정보가 적재 되고,
      아주 천천이 변경 된다.
      • 예외 : 극심한 히스토그램의 수는 딕셔너리 캐시의 크기에 큰 영향을 끼치며 문제를 야기할 수 있지만
        이러한 느린 변화 속도로 인해 성능에 큰 위협이 되지 않느다.
    • 반면 버퍼 캐시의 내용은 시간이 지남에 따라 급격히 변경될 수 있다.
      • 블록들은 버퍼 캐시로 적재되고, 밀려나가고, 버퍼 캐시에 적재된 블록과 리스트를
        일치시키는 작업을 지속적으로 수행해야 한다.
        • 블록은 다른 인스턴스에 의해서도 변경된다.
          • 따라서 리소스에 대한 exclusive 락을 소유하고 있는 한 노드만이 블록을 변경 할 수 있도록
            지속적으로 락 모드를 변경해야만 한다.
  • 2 : 오브젝트( 블록 )를 관리하는 BL 리소스는 실제로 한 인스턴스에서 다른 인스턴스로 이동해야한다.
    BL 락이 필요하다는 것은 해당 락이 관리하는 블록이 필요하다는 것이다.
    • LMS 프로세스들을 이용한 GCS 메커니즘이 필요한 이유이다.
      • GES는 블록에 대한 권한을 다루며 GCS는 실젝 블록을 다룬다.

캐시 퓨전

  • GES : 블록에 대한 권한
  • GCS : 한 인스턴스로부터 다른 인스턴스로 복사본을 전송한다.

디스크 리드 그림 8-4

  • 첫 번째 처리 방식
    • 1. 블록 주소로부터 마스터 리소스의 위치를 계산한다.
    • 2. 리소스에 대한 enqueue를 생성하기 위해 마스터 인스턴스에게 메시지를 보낸다.
    • 3. 만일 리소스가 존재하지 않으면, 마스터 인스턴스는 리소스를 생성하고, 해당 리소스에 enqueue를 등록하고 reader 에게 알린다.
    • 4. Reader는 shadow 리소스 및 enqueue를 생성하고 디스크로부터 메모리로 블록을 읽어 들인다.
  • 두 번째 처리 단계 ( 그름 8-4 )
    • 1. 블록 주소로 부터 마스터 리소스의 위치를 계산한다.
    • 2. 리소스에 대한 enqueue를 생성하기 위해 마스터 인스턴스에게 메시지를 보낸다.
    • 3. 마스터는 리소스의 존재여부 및 존재하면 어느 클러스터 내에 위치하는지 확인한다.
      리소스에 등록된 current enqueue는 어느 인스턴스가 블록을 제공하기 적합한지 알려준다.
      마스터는 리소스에 enqueue를 추가하고, 필요에 따라 리소스에 등록된 다른 enqueue를 변경한다.
      (이것은 다른 인스턴스에 메시지를 전송하다는 것을 의미한다 )
      그리고 선택된 인스턴스에게 블록을 전달하라고 지시한다.
    • 4. 블록을 전송 받으면, reader는 전송이 완료되었다는 것을 마스터 인스턴스에게 알리기 위해 메시지를 전송한다.
      그리고 shadow 리소스와 enqueue를 생성한다.
  • 클러스터 내에서 블록 전송에 관련될 수 있는 노드의 수는 최악의 경우에 세 개 ( 4노드 )
    • 대기 이벤트 : gc current block 2-way( 2노드 ) 및 gc current block 3-way ( 3노드 )
    • 블록을 원하는 노드
    • 해당 리소스에 대한 마스터 노드
    • 현재 해당 블록의 "best" 복사본을 가지고 있는 노드
  • 3node : 마스터이면서 블록을 소윻고 있는 경우의 블록 전송( 2-way )과 마스터가 아닌 인스턴스가 블록을 전송( 3-way )하는 두 가지 경우가 존재한다.
    • 마스터가 될 확률은 1/3, 마스터이면서 블록을 소유할 확률은 1/2
  • 4node : 마스터가 될 확률은 1/4, 마스터이면서 블록을 소유할 확률은 1/3

3노드 일때 테스트

  • 시나리오 : 3노드 RAC 구성한 후 각 노드마다 한 개 세션에서 싱긍 블록 내의 100번의 SELECT-AND-UPDATE( 매번 커밋 )를 반복 수행 ( 필자님 테스트 )
  • 수행 결과를 보면 균형이 맞지 않음을 쉽게 확인할 수 있다.
    • 첫 번째 세트는 블록에 대한 마스터 리소스를 소유한 노드의 결과인 것을 알수 있다.
    • 마스터 노드는 블록의 가장 최신을 소유하고 있는 노드를 알고 있으므로 항상 2-way 오퍼레이션으로 수행된다.
    • 다른 두 개의 노드 : 블록 획득하기 위해 항상 첫번재( 마스트) 노드에게 물어봐야 한다.
      • 만일 첫 번재 노드가 "블록을 소유"하고 있으면 2-way 오퍼레이션으로 수행되고, 그렇지 않다면 3-way 오퍼레이션으로 수행된다.
    • 만일 이 테스트를 4노드로 확장한면, 마스터 노드는 여전희 2-way 오퍼레이션으로 동작하는 것을 볼 수 있다.
      • 하지만 다른 세 개의 노드는 결과는 대략 33번의 2-way 오퍼레이션과 66번의 3-way 오퍼레이션이 발생할 것이다.
        • 이 결과만 놓고 보면, 3-way 오퍼레이션은 2-way 오퍼레이션보다 느리다는 것을 알 수 있다.

CUR( 또는 CR ) 및 Current 읽기

  • 클러스턴 간에 블록을 전송하기 위해서는 다양한 유형의 작은 부작용이 존재한다.
    일반적으로, 이들은 문제를 유발하지 않지만, 특별한 경우에는 중대한 성능 문제를 유발할 수도 있다.

CUR 또는 CR

  • current 블록 : 관련된 버퍼에 exclusive 모드로 핀( pin )을 설정한 후, 블록을 전송하기 전에
    로그 버퍼의 현재 내용을 디스크로 기록하도록 요청한다.
    • gc current block pin time 및 gc current blcok flush time ( 1/100 초 )를 통해 확인 가능
      • 블록 전송을 완료하면, 해당 버퍼는 더 이상 current가 아니다.( 전송한 블록이 current가 된다 ).
        • 하지만 해덩 버퍼는 일정 시간 동안의 실제로 current 였으므로, 오라클은 이것을 PI(past image)상태라고 표현한다.

PI

  • current 복사본을 변경한 후에 인스턴스 장애가 발생하면, 복구 프로세스는 복구 시간을 단축하기 위해 PI 블록을 이용할 수 있다.

PI 처리 방식

  • 1. current(XCUR) 블록을 디스크에 기록한다면, PI를 소유한 모든 인스턴스에게 CR로 다운그레이드 할 것을 알려야 한다.
  • 2. 프로 버퍼를 확보하기 위해 PI를 메모리에서 flush 해야 한다면, PI( dirty 상태인 )를 릴리지 하기 전에, XCUR를 소유하고 있는
    인스턴스에게 current 복사본을 디스크로 기록하라고 메시지를 보내야 한다.( 왜? )
  • 3. 오라클은 CR 복사본을 생성할때 로컬 인스턴스의 PI를 이용하지 않는 것 같고, 항상 XCUR를 소유한 인스턴스에게 메시지를 보내는 것 같다.
  • 4. Current 복사본을 소유한 인스턴스가 해당 블록에 대한 전송 요청을 받으면, CR 복사본을 생성한 후 전송한다.
    • 대기 이벤트 : gc cr block build time 과 gc cr blcok flush time
      • CR 복사본을 생성하기 전에 로그 버퍼의 내용을 다시 한번 flush 한다는 것은 흥미로운 사실이다.

Current 읽기

  • 싱글 인스턴스 : 디스크로부터 메모리를 블록을 읽어 들일 때, 해당 블록의 상태는 일반적으로 XCUR( exclusive current )이다.
    • 이유 : 블록의 current 버전이고, 해당 블록을 소유한 인스턴스와 버퍼는 단 하나이므로, exclusive이기 때문이다.
  • RAC : 일반적으로 SCUR( shared current ) 상태이다.
    • 이유 : 여러 인스턴스가 해당 블록의 동일한 복사본을 메모리에 소유할 수 있고,
      모든 복사본은 current이기 때문이다. ( 만일 update명령어를 통해 메모리를 읽혀진다면 XCUR 상태가 될 것이다. )

8노드 모드 SCUR 모드로 블록을 소유한 상태에서 한 노드가 블록을 변경했다고 가정

  • 변경을 수행한 인스턴스는( 리소스 마스터를 거쳐 ) 다른 모든 인스턴스에 CR로 상태를 변경하라는 메시지를 전송한다.
    • 필자님 : 해당 인스턴스가 변환이 완료되었다는 확인 메세지를다른 인스턴스로부터 대기하는지 여부를 정확히 알지 못한다.
      • "보낸 후 신경 쓰지 않는" 유형의 메시지일 가능성이 있다.
        • 아마도 메시지를 전달하고 전달받는 것에 대한 확인을 위해 리소스 마스터만 댁하면 되는 것 같다. ( ? )

RAC 이상현상 ( 추론 : 부작용 )

  • alter system flush buffer_cache 를 수행하면, 모든 인스턴스의 캐시를 flush한다.
    • 11.2에서 PI블록의 다른 버전이 없다면, PI블록은 flush 되지 않고, CR 상태로 변경된다.

복구 ( 미디어 복구는 배제 ( 싱글과 같음 ) )

  • 인스턴스 복구 - 가용성 ( RAC )
    • 1. 한 인스턴스가 사라지면, 다른 인스턴스들은 즉시 이 사실을 발견한다.
    • 2. 모든 인스턴스들은 싱글 인스턴스 본구를 위한 IR락을 획득하기 위해 경쟁한 후,
      락을 획득한 인스턴스가 장애가 발생한 인스턴스에 대한 인스턴스 복구를 수행하게 된다.
      • 장애가 발생한 인스턴스 캐시 내에 존재했던 블록에 적용된 변경을 복구하고,
        커밋되지 않은 변경은 롤백하는 것을 포함한다.
        장애가 발생한 인스턴스가 소유한 마스터 리소스를 재구성하고, 장애가 발생한 인스턴스에 대한 모든 참조를 GRD를 이용하여
        글린아웃을 수행한 후 GRD를 "rebalancing"한다.
        • 이유 : 인스턴스 개수가 달라졌기 때문에 기존에 사용되던 해시 알고리즘은 더 이상 정상적으로 동작하지 않기 때문이다.

REBALANCING

  • 한 인스턴스가 클러스터에서 분리되면, 오라클은 다른 논리적 인스턴스에 해당 물리적 인스턴스를 할당하기 위해
    맵을 조정하고, 물리적 인스턴스에 대한 마스터 리소스를 재생성한다.
    • 이로 인해 모든 리소스를 재분배할 필요가 없어진다.
      • 하지만 이것은 리소스가 더 이상 공평하게 분배되지 않는다는 것을 의미한다.
      • 2차적 메커니즘이 그 뒤에 수행되어 점진적으로 마스터 리소스를 보다 균등하게( N-1 노드 환경에서 마스터 리소스에 대한 정확한 위치를 매핑함 )

BL 리소스

  • 오라클이 사용하는 해시 알고리즘은 256 블록( 11.2 )단위에 기반한다.
    • 각 데이터 파일은 256개의 연속된 블록의 청크로 나누어지고,
      동일한 인스턴스는 청크내의 모든 블록에 대한 마스터가 된다.
      이것은 테이블스캔이 수행되는 동안, 각 multi-block 읽기 요청은 하나의 인스턴스에 속한
      블록들일 가능성이 높다는 것을 의미한다.( 특히, 1MB 단위로 생성된 Locally Managed Tablespace( LMT )환경의 경우 ).
      • 클러스터 내에 인스턴스를 추가할 때 BL 리소스를 재분배하는 오라클의 알고리즘을 산출하는 것은 다소 어렵다
        • 아마도 이것은 각 인스턴스의 모든 N번재 청크의 관리를 새로운 노드로 전달하는 것 같다 ( 작가님 왈 )
  • RAC 복구의 장점 : 완전히 자동화되었다는 것
  • RAX 복고의 대한 단점 : GRD의 재구성과 rebalancing으로 인해 짧은 순간 동안 인스턴스가 동결된다는 것이다.

Shadow 리소스 와 PI

  • 오라클은 장애가 발생한 인스턴스의 마스터 리소스 이미지를 재구성하기 위해 살아 있는 노드들의 모든 shadow 리소스를 스캔한다.
  • 오라클은 마스터 리소스를 리빌드할 때, 장애가 발생한 인스턴에 대한 enqueue를 소유한 마스터 리소스를 제외할 수 있다.
    • 예외적으로 BL 리소스에 exclusive 락을 설정한 마스터 리소스는 제외할 수 없다.
      해당 블록들을 복구가 필요하기 때문이다.
  • 복고를 수행할 때, 오라클은 리두 로그와 관련된 작업량의 상당부분을 감소시킬 수 있다.
    • PI는 블록의 최근 복사본이며, 디스크에 기록되었을 가능성이 높기 때문이다.
      • PI블록에 대한 리두 레코드의 SCN이 PI블록의 마지막 변경 SCN 보다 자다면, 복구 시에 적용할 필요가 없다.

시퀸스

  • 생성 구문
  • dmbs_metadata.get_ddl

시퀸스 캐싱

  • "캐시"는 전통적인 캐시와 다른 의미이다. -> "목표"
    • 시퀸스 캐시를 100를 100으로 설정하면 오라클은 100개의 번호를 생성 및 저장하지 않는다.
      • 이것은 매우 캐시 값을 설정하더라도 더 많은 비용을 지불하지 않는다는 의미이다.
  • 시퀸스는 SGA 내에 캐시된다.
    • 많은 사람들이 시퀸스는 세션에 의해 캐시된다고 생각한다.

시퀸스 동작 원리

  • 1. 하나의 시퀸스는 seq$라고 불리는 테이블 내에 한 로우로 정의된다.
  • 2. 시퀸스를 처음 채번할 때, 시퀸스의 시작 값은 캐시 크기에 의해 증가되고, seq$의 로우에 기록된다.
  • 3. 그 이후, 오라클은 메모리 내의 current 값과 target 값을 관찰한다.
  • 4. nexval을 요청할 때마다, 오라클은 current 값을 증가하고, 그것을 제공하기 전에 target 값과 비교한다.
  • 5. 만일 current 값과 target 값이 같다면, 오라클은 target 값에 캐시 크기를 더한 새로운 target 값을 생성한후 seq$내의 로우를 변경한다.

시퀸스 동작 원리 TEST

  • 11G에서는 PL/SQL내에서 시퀸스 값을 변수에 할당하는 것이 가능해졌다.
    • 하지만 내부적인 구현은 여전히 SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL을 사용한다).
    • 10046 TRACE ( TKPROF 실행 )
  • 첫 번째 명령어는 오라클이 highwater( =1 ) 와 cache( =20 )값 등을 seq$ 테이블에 입력 ( 인서트 ==시퀸스 생성 )
  • 이후 20번재 호출 때마다 highwater값이 변경된다. ( 업데이트 )
  • 만일 캐시 크기의 기본설정값을 변경하지 않고 수 많은 nexval을 호출하면, 다수의 update 와
    리두가 발생할 것이다. 이것은 RAC 뿐만 아니라 싱글 인스턴스 환경에서도 바람직하지 않다.
    또한. SQ 락 및 dc_sequences 에 대한 딕셔너리 캐시를 관리하는 래치에 대한 대기 현상이 발생할 수 있다.
    SQ 락은 세션이 highwater mark를 변경하는 동안 획득하는 락이다.
  • RAC 시스템에서는 상황이 더 나빠질 수 있다. 변경하려는 로우를 포함한 seq$의 블록이 끊임없이 클러스터 내에서
    이동할 수 있기 때문이다. 이런 경우는, 동일한 시퀸스를 사용하는 서로 다른 인스턴스에서 사용하는 경우에 발생한다.
  • Seq$ 테이블은 블록당 80~90 로우를 저장할 수 있다. 따라서 시퀸스 몇 개만을 사용하더라도 인스터스간의 트래픽양은
    증가할 수 있다.( 심지어 서로 다른 인스턴스간에 서로 다른 시퀸스를 사용하는 경우에도)
    이런 경우 싱글 인스턴스는 buffer busy wait 대기 이벤트가 발생될 수 있고, RAC에서는 gc buffer busy wait 대기 이벤트가 발생될 수도 있다.

Ordered 시퀸스

  • RAC 환경에는 기본적으로 각 인스턴스는 시퀸스에 대한 각자의 세트를 생성한다.
    만일 4노드 RAC 환경에서 캐시 크기가 20 이라면, 한 인스턴스는 101 ~ 200, 다음 인스턴스는 121~140 등 값을 갖게 된다.
    • 시퀸스 값이 생성되고 사용되는 순서가 완벽히 순차적일 수 없다는 것을 의미한다.

시퀸스, ORDER 및 AUDIT

  • 시퀸스는 트랜잭션 처리를 하지 않기 때문에, 일부 값이 누락 될 수 있다. 예를 들어,
    nextval을 호출한 후 롤백을 수행한면, 해당 값을 잃어버리게 된다. 따라서 시퀸스의 nocache 옵션을 이용하여
    연속적인 순차적 번호를 보장 및 audit 목적의 요구 사항을 처리 할 수 없다.
    • 만일 RAC 시스템에서 캐시 크기를 0 (nocache)으로 설정하면, 인스턴간의 seq$ 블록의 전송으로 대량의
      캐시 전송을 유발한다.
    • 또한 시퀸스 캐시는 0이 아닌 값( 심지어 큰값)으로 설정하였지만 order 옵션을 적용하면, 언두와 리두 생성 측면에서는 비교적
      나쁘지 않지만, 대량의 트래픽이 발생하게 된다.
      • 각 인스턴스는 시퀸스에 대한 자신만의 캐시를 갖는 것이 허용된다.
        대신, highwater값과 current 값을 가진 메모리 위치는 하나이다.
        • 메모리 위치는 특별한 글로벌 락 SV락에 의해 제어되고 시퀸스의 current 값은 인스턴스 간에 전달한다.
          따라서 특정 시점에는 단 하나의 값만이 존재하고,한 인스턴스만 그 값ㅇ르 증가실킬 수 있으므로,
          순차적인 값이 생성되다.( 값의 누락을 보잘할 수 없다 )

SV 락

  • v$lock_type 뷰를 보면 SV락 유형에 대해서 다음과 같이 정의한다.
    • "Lock to ensure ordered sequnce allocation in RAC mode" ( RAC 모드에서 순차적인 시퀸스 하당을 보장하기 위한 락).
      • SV 락의 첫 번째 파라미터( id1 )는 시퀸스의 오브젝트 아이디이다.
        그러나 프로세스가 SV락을 획드하려고 시도할 때 V$LOCK 뷰 내에서는 어떤한 것도 확인할 수 없으며,
        트레이스 파일이나 V$SESSION_EVENT 뷰에서도 관련된 어떠한 enqueue도 확인 할 수 없다.
        대신에, DFS lock handle 대기를 확인할 수 있으며, 해당 대기 이벤트의 첫 번째 파라미터를 디코딩하면 SV락을 발견할 수 있다.
      • SV 락을 모드 6(exclusive)으로 획득할 것이라고 기대한다.
        하지만 DFS lock handle 대기이벤트의 첫 번째 파라미터는 디코딩하면 락 모드가 5인 것을 알수 있다. ( RAC에서 exclusive 락 )
  • 자주 사용되는 시퀸스에 order 옵션을 사용하면, latch:ges resource hash list 와 row cache lock 대기 이벤트가 발생할 수 있다.
    • 전자는 RAC와 관련된 리소스가 동일한 해시 테이블 및 링크드 리스트를 사용한다는 것을 의미
    • 후자는 시퀸스는 V$ROWCACHE 내의 항목과 매우 밀접히 관련되어 있다는 점과,
      row cache 내의 항목을 변경하고 flush 하기 위해 필요한 작업(및 시간)이 싱글 인스턴스보다 RAC에서 더 많다는 사실을 상기시켜준다.

시퀸스와 인덱스

  • "(의미 없는) primary key"또는 unique key로 사용하면, 항상 최대값을 입력하게 된다.
    • 인스턴스간에 hot-spot이 발생하게 되며 gc buffer busy waits를 유발
      • 항상 즈가하는 값을 입력하려는 모든 경웨 해당된다. ex : current timestamp

인덱스 ITL 이슈

  • 오라클의 B-tree 인덱스 구현 내에는 오래된 결함( 또는 버그, 아마도 )이 존재
  • 리프블록이 분할(split)이 발생할 때 다수의 프로세스가 동시에 해당 리프 블록에 인덱스 항목을 입력하려고 시도하면,
    분할된 두 개의 리프 블록 내에 불필요하게 많은 ITL 엔트리가 생성되는 결과를 초래한다.
    새로운 리프 블록의 ITL 리스트는 적어도 분할 전 만큼은 크고, ITL 엔트리는 절대 줄어들지 않기 때문이다.
    이로 인해 모든 인덱스 리프 블록은 ITL 엔트리를 위한 공가을 위해 절반을 사용할 수도 있다.
    • 오라클 초기 버전에서의 해결방법은 단순하다.
      인덱스의 maxtrans를 적절히 ( 너무 크지 않게 ) 조정하는 것이다.
      • 불행히도 10g 이상부터, 오라클은 maxtrans 를 무시한다.
        • 이 문제에 대해서는 필자님의 블로그의"index explosion" 카테고리에 있는 몇 개의 긍르 참조하기 바란다.
          • 12.1에서 해결될 예정이며, 이미 10.2 버전에도 몇개의 backport를 제공한다.

ASSM ( automatic segment space management )

  • ASSM이 소개되기 전에는, 테이블에 대한 동시 입력 시 발생하는 문제를 경감시키기 위해 다수의 free list 및
    다수의 free list groups를 사용하였다.
  • ASSM은 서로 다른 RAC 인스턴스간에는 서로 다른 비트맵 블록을 사용하도록 허용하으로써,
    서로간의 입력을 분리할 수 있으며, 테이블에 대한 buffer busy waits 문제를 DBA가 고민하지 않도록 한다.
    • 하지만 인덱스 hot-spot을 분산시킬 수는 없다.
      • 인덱스 엔트리는 임의의 위치에 저장할 수 없고, 반드시 정확한 위치에 정장되기 때문이다.

인덱스 hot-sport 문제를 처리하기한 방안

  • reverse-key 인덱스로 인덱스를 재생성 하는 것이다.
    • reverse-key 인덱스의 각 컬럼의 값을 역순으로 변경된 후 인덱스에 저장된다.
    • 부작용 : 만일 대부분의 쿼리가 "최근" 데이터만 조회한다면, 전체 인덱스 중에 아주 작은 부분만을 메모리 내에
      적재하면 된다. 하지만 만일 역순으로 저장한다면 최근 데이터는 인덱스의 넓은 범위에 분산되어 저장된다.
      따라서 이전과 동이한 캐싱 효과를 얻기 위해서는 대부분의 인덱스 블륵을 메모리에 적재해야 한다.

인덱스 hot-spot 문제를 해결하기 위한 두 개의 대안

  • 1. 가장 단순한 방법은 매우 큰 캐시크기의 시퀸스를 사용 ( 5,000 ~ 50,000 )
    • 각 인스턴스는 수 천정도의 차이가 나는 값을 입력한다.
      • 이방법의 결점은 리프 블록 분할의 대부분이 50/50 분할이라는 것이다. (최대값을 입력하는 경우느 제외하면)
  • 2. 인덱스 해시 파티션을 이용하는 것이다.
    • 시퀸스 번호를 해시 키로 이용하여, 인덱스를 (예를 들어) 16개의 서로 다른 파티션에 입력한다면
      최대값 입력 시 하나의 hot-sport을 16개( 해시 파티션의 개수는 항상 2의 지수승을 이용하는 것이 가장 효과적이다)
      의 warm-sport으로 전환할 수 있다.( 노드 분할 )