2009년 3월 16일 월요일

Parallel query option의 사용 [ 펌]

No. 10801

Parallel query option의 사용
----------------------------

parallel query option을 사용하면, 여러 개의 process가 하나의 SQL 문을 
나누어 동시에 작업하여 성능 향상에 도움을 줄 수 있다.

여기에서는 parallel query에 대한 다음과 같은 사항을 정리하였다.
(1)  parallel query option이 사용되기에 적당한 환경
(2)  parallel query processing이 사용되어질 수 있는 SQL 문장의 종류
(3)  parallel query 수행을 위한 정의 방법
(4)  degree의 의미 및 결정
(5)  parallel query processing의 tuning 방법


1. PARALLEL QUERY OPTION이 사용되기에 적당한 환경

(1)  의사 결정 애플리케이션(decision support application)이나 대용량
     데이타베이스 환경 등 이러한 환경에서의 data-intensive한 연산의 성능을
     향상시킨다.
(2)  symmetric multi processor (SMP), clustered system, massively 
     parallel system, 하나의 시스템에 여러개의 CPU가 있는 경우 query 
     processing이 효과적으로 각 CPU에 할당되어 처리될 수 있다.
(3)  datafile이 여러 개의 disk drive에 나누어져 있는 경우 query의 대상이 
     되는 데이타들이 하나의 disk에 모여 있다면, 하나의 query를 여러 개의 
     process로 나누어 동시에 작업한다 하더라도 I/O 측면에서는 효과가 없다.

주의) 현재 사용 중인 시스템의 CPU와 disk controller 사용율이 이미 100%에 
가깝다면, parallel query option이 오히려 부하를 증가시킬 뿐이므로 system
resource를 증가시킨 후 parallel query option을 고려하여야 한다.


2. PARALLEL QUERY PROCESSING이 사용되어질 수 있는 SQL 문장의 종류

(1)  SELECT 문장
(2)  UPDATE, INSERT, DELETE 문 내의 subquery
(3)  CREATE TABLE ... AS SELECT 문
(4)  CREATE INDEX 문

위와 같은 문장 내에 최소한 하나의 full table scan operation이 포함되어야 query가 parallelize된다.


3. PARALLEL QUERY 수행을 위한 정의 방법

parallel query가 수행되도록 하려면 다음과 같이 3가지 방법으로 정의할 수 있다.

(1)  instance level, init<SID>.ora file 내에 정의한다.
(2)  table level, create/alter table 문장에서 정의한다.
(3)  query level, PARALLEL hint에서 정의한다.

Query level의 PARALLEL hint는 table 차원의 정의와 init<SID>.ora file 내의
PARALLEL parameter에 우선한다.  마찬가지로 table 차원에서 정의된 
parallelism의 degree가 init<SID>.ora 화일 내의 PARALLEL parameter에 우선
한다. 그러므로, parallel mode로 수행되는지는 instance나 table level의 
check만으로는 부족하다.  또한, query 내에서 PARALLEL hint를 바르게 사용하지
못한 경우 comment로 인식되므로 주의하여야 한다.


주의) instance level이나 table level에 parallel query option을 거는 경우, 
table의 정보가 바르게 analyze되지 않았거나, 그 외의 이유로 인하여 예상치 못한
문제를 접하는 경우가 많으므로 가능한 instance나  table level로는 parallel 
query option을 setting하지 말고 필요한 query마다 hint를 이용하여 parallel을
지정하는 것이 바람직하다.


(1) instance level 정의

다음과 같은 init<ORACLE_SID>.ora parameter에 의해 정의된다.

parallel_max_servers 
- instance 당 max slave 
  (0는 parallel query option을 사용하지 않음을 의미)

parallel_min_servers 
- instance가 startup 당시 최소한 뜨게 되는 slave의 수.
  만약 parallel_min_servers를 설정하지 않으면, default는 0이며, 
  이 파라미터는 parallel query server가 자주 start되고 shutdown되는 경우
  일정한 갯수의 query server는 항상 떠있게 한다.

a. 7.3 미만

parallel_default_max_scans 
- 하나의 query 수행을 위해 default로 사용되어지는 query server 갯수의 
  최대값. 이 값은 PARALLEL hint나 table 정의 시 PARALLEL 절이 없는 경우 
  영향을 미친다.
parallel_default_scansize 
- table의 size가 analyze 문으로 인해 추측이 되는 경우 특정 table을 위해 
  필요한 query server의 갯수를 결정하기 위해 필요한 parameter이다.  
  table의 블럭 수를 이 값으로 나누면, 그것이 query를 위해 필요한 query 
  server의 갯수이다.  이렇게 계산된 query server의 갯수는
  PARALLEL_DEFAULT_MAXSCANS paramter를 초과할 수 있다.

b. 7.3 이후

parallel_min_percent 
- parallel query 수행을 위해 필요한 query slave의 최소 percentage.   
parallel_min_percent / 100 개 이상의 query slave가 사용 가능하지 않으면 
query는 오류를 발생시키며, 이 값이 설정되어 있지 않으면, 사용 가능한 
qeury slave만을 이용하여 parallel query를 수행한다.

이 외에도 parallel_server_idl_time, parallel_default_max_instances, 
recovery_parallelism 등의 parameter가 있으나, 이러한 parallel query와 
관련한 어떠한 parameter도 parallel query option을 위해 반드시 필요한 
것은 아니다.


(2) table level 정의

table은 n degree의 parallelism을 가지도록 create 혹은 alter될 수 있다. 
이것은 init<SID>.ora files 내의 PARALLEL_DEFAULT_MAX_SCANS나
PARALLEL_DEFAULT_SCANSIZE가 정의되어 있더라도 이러한 값에 우선한다.
다음과 같이 지정할 수 있다.

CREATE TABLE DEPT
PARALLEL (DEGREE 5)
(DEPTNO NUMBER(2),
DNAME VARCHAR2(20));


(3) Query statement

PARALLEL hint를 사용하면 query에 포함된 table의 degree를 설정할 수 있다. 
예를 들어, 다음과 같이 hint를 적어 degree 4로 parallel query option을 
실행하도록 할 수 있다.
이 때 parallel이란 글자와 괄호( '(' )사이에 blank를 넣지 않도록 한다.
      
       select /*+ PARALLEL(emp, 4) */  * from emp;

다음과 같이 NOPARALLEL hint를 사용하면, parallel query option을 사용하지 
않도록 할 수 있다.

       select /*+ NOPARALLEL(emp) */ * from emp;


4. DEGREE의 의미 및 결정

parallel query에서 degree란 하나의 operation 수행에 대한 server 
process의 갯수이다. 이러한 degree 결정에 영향을 주는 요인들에는 다음과 
같은 것들이 있다.

(1)  system의 CPU 갯수
(2)  system의 maximum process 갯수
(3)  table이 striping되어 있는 경우, 그 table이 걸쳐있는 disk의 갯수
(4)  data의 위치 (즉, memory에 cache되어 있는지, disk에 있는지)
(5)  query의 형태 (예를 들어 sorts 혹은 full table scan)

한 사용자만이 parallel query를 사용하는 경우, sorting이 많이 필요한 
작업과 같은 CPU-bound 작업의 경우는 CPU 갯수의 1 ~ 2배의 degree가 적당하며,
sorting보다는 table scan과 같은 I/O bound 작업의 경우는 disk drive 갯수의 
1 ~ 2배가 적당하다.
동시에 수행되는 parallel query가 많은 경우에는 위의 각 사용자의 degree를 
줄이거나 동시에 사용하는 사용자 수를 줄여야 한다.


5.  PARALLEL QUERY PROCESSING의 TUNING 방법

(1) explain plan

explain plan을 이용하면, object_node와 other column을 이용하여 query가
어떻게 병렬로 처리되는지를 알 수 있다. 
분산 환경이 아닌 경우 OBJECT_NODE 컬럼은 operation 수행 결과값이 다음 어느
operation에 사용되어지는지를 나타내며, OTHER 컬럼은 각 query server를 
이용하여 어떻게 query가 진행되는지가 기술된다. OTHER 컬럼의 type이 LONG인 
관계로 전체 text가 나오지 않을 경우, 
$ORACLE_HOME/rdbms/admin/utlxplan.sql file 내에서 OTHER 컬럼의 type을
VARCHAR2로 바꾼 후 plan_table을 다시 만들어 수행하면, 전체 text를 확인할 
수 있다.

참고) explain plan의 사용법은 <Oracle7 Server Application Developer's 
Guide>나 한국오라클의 bulletin <Explain Plan 사용법>을 참조하도록 한다.

(2) parallel query 문장과 explain plan

SQL 문: SELECT /*+ parallel(dept, 4) */ 
 dname, MAX(sal), AVG(SAL)
       FROM dept, emp
 WHERE dept.deptno = emp.deptno
 GROUP BY dname;

위 문장 수행에 대한 explain plan의 결과는 다음과 같으며, parallel hint에
dept만 parallel query 처리하도록 지정하여 EMP를 full scan하는 부분은
OTHER 컬럼이 null인 것을 알 수 있다. 만약, dept와 emp를 모두 parallel
processing하고자 한다면 hint 지정 시 /*+ parallel(dept, 4, emp, 4) */ 
와 같이 지정하면 된다.

Query Plan     OBJECT_NODE
-------------------------------       --------------------------
OTHER
------------------------------------------------------------------
SELECT STATEMENT     Cost =6

    SORT GROUP BY    :Q30003
SELECT /*+ CIV_GB */ A1.C0, AVG(A1.C1), MAX(A1.C2) 
FROM :Q30002 A1 
GROUP BY A1.C0

    HASH JOIN     :Q30002
SELECT /*+ PIV_GB */ A1.C0 C0, AVG(A1.C1) C1, MAX(A1.C1) C2 
FROM (SELECT /*+ ORDERED NO_EXPAND USE_HASH(A3) */ A2.C1 C0, A3.C1 C1,
                          A3.C1 C2
      FROM :Q30001 A2, :Q30000 A3 
      WHERE A3.C0=A2.C0) A1 
GROUP BY A1.C0

    TABLE ACCESS FULL DEPT  2          :Q30001
SELECT /*+ ROWID(A1) */ A1."DEPTNO" C0, A1."DNAME" C1 
FROM "DEPT" A1 
WHERE ROWID BETWEEN :B1 AND :B2

    TABLE ACCESS FULL EMP  1   :Q30000

(3)  parallel processing을 이용하지 않은 SQL 문장과 explain plan

SQL 문: SELECT /*+ NOPARALLEL */ dname, MAX(sal), AVG(SAL)
 FROM dept, emp
 WHERE dept.deptno = emp.deptno
 GROUP BY dname;

위의 문장에 대한 explain plan은 다음과 같이 OBJECT_NODE와 OTHER 컬럼에 
어떤 값도 들어 있지 않다.

Query Plan   OBJECT_NODE           OTHER
-----------------------------   ----------------------   -----------
SELECT STATEMENT     Cost =6
  SORT GROUP BY
    HASH JOIN
      TABLE ACCESS FULL DEPT  2
      TABLE ACCESS FULL EMP  1


(4) dynamic view

query가 parallel mode로 실행되고 있는 중에 v$pq_sysstat를 조회하면, 
parallel query server의 busy, idle 상태 및 server started, server 
shtudown된 상태를 알 수 있다.

다음 예와 같이 query하면, 현재 수행되는 parallel query를 위해 사용되어지는
query server의 갯수를 알 수 있다. 이 값을 통해
parallel_min_servers의 값이나 degree의 설정에 참조할 수 있다.

os>  sqlplus system/manager
sql> select * from v$pq_sysstat where statistics = 'Servers Busy';

STATISTICS VALUE
---------------  ----------
Servers Busy      3


(5) OS process

OS 상태에서 다음과 같이 수행하면 현재 OS에서 구동되어 있는 parallel query
process를 확인할 수 있다. init<ORACLE_SID>.ora file 내에 parallel_min_servers의 값이 n으로 지정되어 있다면, 다음 명령을 수행하는 순간에 parallel processing에 참여하고 있는 process가 n보다 작더라도,  최소한 n개의 process가 구동되어 있게 된다.

ps -ef | grep p00
oracle  2512     1  0.0 16:03:11 ??           0:12.09 ora_p001_ORA7
oracle 29162     1  0.0 16:03:11 ??           0:30.16 ora_p000_ORA7

이 명령을 통하여 현재 구동되어 있는 parallel query process의 갯수와  현재까지 사용한 CPU time 등을 알 수 있다.

출처 : http://database.sarang.net/?inc=read&aid=17307&criteria=oracle&subcrit=&id=&limit=20&keyword=&page=2

2009년 3월 6일 금요일

알티베이스, 하이브리드 DBMS 누적매출 200억

알티베이스, 하이브리드 DBMS 누적매출 200억

디지털타임스 | 박상훈 | 입력 2009.03.04 08:03

2005년 이후 두자릿수 성장
올 상반기 공공시장 기대감


■ 희망을 이끄는 강소기업-SW

최근 3~4년은 알티베이스(대표 김기완)에게 기회이자 위기였다. 본래 메모리기반 데이터베이스관리시스템(DBMS) 제품이었던 `알티베이스'의 최신 4버전을 2005년 출시하면서 디스크기반 DBMS로 영역을 확대해 `하이브리드 DBMS'를 출시한 것이다.

업계에서는 기대와 우려가 교차했다. 기존의 알티베이스 3 버전이 시장에서 평가를 받으면서 자리를 잡아가는 시기였다는 점도 위험 부담 쪽의 의견에 무게를 더했다.

그러나 단일 DBMS내에서 MM DBMS와 DR DBMS를 제공한다는 하이브리드 DBMS `알티베이스 4'의 등장은 당시 이기종 환경에서 중복투자를 피하는 해법을 찾던 기업들의 관심을 끌어 모으는데 성공했다. 2005년 이후 알티베이스4는 기존의 주력 시장이었던 금융, 통신은 물론, 제조, 공공 등 다양한 산업 분야에 걸쳐 150여개 사이트, 300여개 프로젝트에 공급했다. 하이브리드 DBMS 매출만 누적 200억원이 넘는다.

이러한 성과는 2005년 이후 알티베이스의 두 자리 수 성장의 밑거름이 됐다. 2005년 70억, 2006년 85억, 그리고 지난해에는 120억원을 달성하며 성장가도를 질주하고 있다.

특히 이러한 성과는 외산 업체가 90% 이상을 석권하고 있는 시스템 소프트웨어(SW) 분야에서 국내 원천 기술로 독자 개발했고 `알티베이스'라는 단일 제품 라이선스 매출만으로 100억원을 돌파했다는 점에서 의미가 있다는 평가다.

지난해 알티베이스가 성장세를 유지할 수 있었던 데는 무엇보다 공공시장과 증권, 통신 시장에서의 수성이 가장 컸다. 시장의 요구를 반영해 신기능을 추가한 `알티베이스 5'를 출시해 범용 DBMS 시장을 직접 겨냥하면서도 하드웨어 영업 등 다른 분야로 영역을 넓히지 않고 DBMS 영업에만 집중한 것도 주효했다.

그 결과 지난해 가장 큰 SW 분리발주 프로젝트의 하나였던 국방부 물자탄약정보체계 프로젝트를 비롯해 서울메트로 전사자원관리(ERP) 구축 사업, 근로복지공단 차세대 노동보험시스템 프로젝트 등 굵직한 레퍼런스를 확보했고 서경대학교 등 교육시장 진입을 위한 교두보도 확보했다.

알티베이스는 올해 전반적인 IT 투자 축소 움직임에도 불구하고 지난해 대비 50% 이상 성장한 180억원을 매출 목표로 잡았다.

상반기 가장 기대를 걸고 있는 시장은 예산의 70%를 조기 집행하겠다고 한 공공시장이다. 지난해 공공 부문에서 대규모 핵심 업무 시스템을 윈백 했던 프로젝트가 지난해 말부터 실제 가동에 들어가면서 그 결과를 지켜보고 있던 다른 공공기관들도 큰 관심을 보이고 있다는 것이 업체 측의 설명이다.

민간 영역은 대규모 IT 투자가 다소 주춤할 것으로 보이지만 통신 부문의 KT-KTF 통합과 같은 초대형 이슈가 있어 지난해 미뤄진 프로젝트와 통합에 따른 후속 프로젝트, 신규 시스템 구축 프로젝트 등 합병 특수를 기대하고 있다.

중국발 통신업체 합병 특수도 있다. 기존에 알티베이스를 사용해 온 거대 통신업체인 차이나유니콤이 차이나네트콤을 인수합병하면서 이미 관련 프로젝트 여러 건이 물밑에서 진행중이다. 양 사는 통합 작업과 3G 이동이라는 이슈도 있어 올해 알티베이스의 해외매출은 지난해 대비 최대 2배 늘어, 전체 매출의 20%를 기록할 것으로 전망하고 있다. 알티베이스는 중국시장에서 하이브리드 DBMS의 수요를 추가로 발굴하기 위해 현지 파트너 업체들과의 협력을 강화해 나갈 계획이다.

시장의 변화가 예상되는 만큼 알티베이스의 제품군에도 다소 변화가 예상된다. 기존 제품의 품질을 높이면서 동시에 새로운 시장 기회를 발굴하기 위한 것으로, 이기종 DBMS 환경에서 알티베이스를 손쉽게 적용하고 활용할 수 있는 DBMS 부가 툴을 추가로 개발하고 있다. 알티베이스는 올해 내에 최소 두 종류 이상의 DBMS 부가 툴을 선보일 예정이다.

김기완 알티베이스 대표는 "경기침체가 본격화되면서 기업들이 총소유비용(TCO) 및 투자대비효과(ROI)에 최적화된 솔루션에 큰 관심을 보이고 있다"며 "메모리는 물론 디스크 기반 기능까지 지원하는 대안 DBMS로 알티베이스가 활발하게 검토될 것"이라고 말했다.

박상훈기자 nanugi@
< Copyrights ⓒ 디지털타임스 & dt.co.kr, 무단 전재 및 재배포 금지 >

2009년 3월 4일 수요일

DELAYED BLOCK CLEANOUT PROBLEM (ORA-1555)

제품 : ORACLE SERVER

작성날짜 : 2004-10-26

delayed Block Cleanout Problem (ORA-1555)

수만 개의 row를 가진 테이블을 갱신하는 transaction이 있다고 가정하자. 
테이블의 데이타를 갱신하기 위해 상기 작업은 수많은 블록을 접근한다. 
유저가 commit을 했을 때 오라클은 이러한 블록들을 다시 접근하여 permanent한 
형태로 만들어 주지 않는다. 그러한 작업은 다음 transaction에 의해 수행되며
그 작업은 update에 의해 영향을 받은 block을 접근하여 그것을 깨끗한 형태로 
다시 만들어 주는 작업을 말한다. (즉 delayed block cleanout 이라 함)

오라클이 데이타베이스 블록을 update 시마다 그 블록의 header에 롤백 정보를 
가지고 있는 롤백 세그먼트에 대한 pointer 정보를 가지게 된다. 
(이러한 정보는 다음에 유저가 'undo' 작업을 요구할 때 사용된다)
Commit되는 시점에서 데이타베이스는 단순히 rollback segment header entry에
commit이 되었다는 표시만 하게된다. 그 후 변경된 블록을 다른 transaction이 

다시 방문할 때 오라클은 그 데이타블록의 헤더정보를 보고 이것이 과거 어떤 
시점에 변경되었다는 것을 알게된다. 
이 때 데이타베이스는 그 변경된 내용이 commit되었는지 아니면 아직 commit되지
않았는지 확인할 필요가 있다. 이러한 작업에는 이전 갱신 작업에서 사용된
rollback segment의 header정보를 참조하여 commit되었는지 그렇지 않은지
판단하게 된다. 

그 블록이 commit되었다는 것을 알게 되면 data block의 header는 다시는 상기
작업을 반복하지 않도록 수정된다. 

이러한 작업을 정상적으로 수행하는 도중에 rollback segment transaction 
table의 overwriting에 의해 ORA-1555가 발생할 가능성이 있다. 다음에 그 
예를 들어본다. (어떤 SCN을 가진 QUERY ENVIRONMENT을 *QENV scn*이라 한다)

EXAMPLE>
1. session 1은 time T1에 QENV 50

2. session 1 은 query 도중 B1 block을 select한다. 

3. session 1은 SCN 51에 block을 update 작업을 수행한다.

4. session 1은 상기 갱신작업을 commit한다.
(이 때 다른 transaction들은 위의 rollback segment information을 
overwrite할 수 있다.)

5. 임의의 다른 session이(session 1일수도 있고 다른 session들일 수도 있다.)
일련의 transaction commit 들에 의해서 같은 rollback segment를 사용한
다. 
각각의 transaction들은 rollback segment transaction table의 slot들을 
사용하게 되며 slot들은 circular하게 사용되므로 결국에 가서는 이전의 
slot을 overwrite하게 된다. 오라클은 commit된 transaction에대해서는 
재사용할 수 있다. 

6. session 1의 query가 변경된 block을 다시 접근한다고 가정하면 이전 image
가 필요하게 된다.
이때 오라클은 data block에 의해 지칭되는 rollback segment header의 
transaction slot을 찾게된다. 그때 오라클은 다른 transaction들에 의해
overwrite되었다는 것을 알게 된다. 오라클이 변경된 rollback segment 
transaction table을 원래 상태로 되돌리지 못한다면 ORA-1555 에러 메시
지를 내보내게 된다.

해결방법 >
1. 일반적인 ORA-1555 를 해결하는 방법을 사용한다. 
2. 만약 delayed block cleanout에 의한 원인이 의심되면 아래와 같은 방법을 
이용하여 변경된 block들을 clean out 시킨다. 

Alter session set optimizer_goal = rule;
select count(*) from table_name; 


Reference Documents


<Note:40689.1>

ITL Entry

ITL(Interested Transaction List)은 특정 블록을 변경하고자 하는 트랜잭션의 목록을 의미하며, 블록의 헤더에서 그 정보를 관리한다. 블록을 변경하고자 하는 모든 트랜잭션은 블록 헤더의 ITL의 엔트리 중 하나로 자신을 등록해야 한다. 만일 ITL이 약속된 최대치, 즉 MAXTRANS에 의해 지정된 값을 초과하거나 블록 내의 여유공간이 부족해서 엔트리를 등록하는 것이 불가능한 경우, 프로세스는 이미 ITL에 엔트리를 등록한 프로세스가 Exclusive하게 획득한 TX 락을 Shared 모드로 획득하기 위해 대기하게 된다. 이때의 대기현상은 enq: TX - allocate ITL entry 이벤트로 관찰된다. 테이블을 생성할 때 부여하는 세가지 속성값이 ITL에 영향을 준다.

  • INITRANS : 블록 헤더마다 몇 개의 ITL 엔트리를 미리 확보할 지를 결정한다. 가령 INITRANS의 값을 10으로 주면 10개의 동시 트랜잭션을 위한 공간이 마련된다.
  • MAXTRANS : 최대 몇개의 ITL 엔트리를 허용할지를 결정한다. 가령 MAXTRANS의 값을 50으로 주면 최대 50개까지의 동시 트랜잭션을 허용한다. MAXTRANS의 기본값은 255이며, 오라클 10g부터는 MAXTRANS는 255로 고정된다. 즉, MAXTRANS 값을 지정해도 오라클은 이 값을 무시하며 항상 255의 값을 사용한다.
  • PCTFREE : 블록이 최초 생성될 때는 INITRANS에 지정된 값만큼 ITL 엔트리가 확보되었다가, 동시 트랜잭션이 증가하면 PCTFREE로 확보된 영역 내에서 MAXTRANS만큼 추가로 확장된다.

만일 동시 트랜잭션이 왕성할 것으로 예상되는 테이블이라면 INITRANS를 충분히 주는 것이 좋다. INITRANS를 충분히 주면 동적으로 공간을 확보하는 오버헤드가 줄어들며, ITL 엔트리 부족에 따른 TX 락 경합이 발생할 확률도 줄어든다. 오라클 10g부터는 MAXTRANS의 값이 255로 고정되므로 잘못된 MAXTRANS 값 지정으로 인해 성능 문제가 생길 소지가 사라졌다. PCTFREE 값을 비정상적으로 작게 설정하는 경우 ITL을 동적으로 확장할 여유공간이 부족해서 문제가 될 수도 있다. 오라클 9i에서 MAXTRANS 값을 임의로 작게 준 경우 TX 락 경합이 어떻게 발생되는지 살펴보자.(오라클 9i에서 테스트를 하는 이유는 오라클 10g에서는 MAXTRANS가 255로 고정되었기 때문이다)

SQL> -- maxtrans 값을 2 로 준다. 이 경우 세개 이상의 세션이 동시에 블록을 변경하지 못한다.
create table tx_itl_test(id number)
initrans 2 maxtrans 2;

-- 총 5건의 데이터를 생성한다.
insert into tx_itl_test values(1);
...
insert into tx_itl_test values(5);
-- dbms_rowid package를 이용해서 같은 블록안에 들어가 있는 로우를 확인한다.
 
SQL> select id, dbms_rowid.rowid_block_number(rowid) from tx_itl_test;

       ID DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
        1                               175362
        2                               175362
        3                               175363
        4                               175363
        5                               175363
id값이 3, 4, 5 인 로우들이 175363번 블록에 있으므로 이 세개의 로우에 대해 동시에 다른 세션들에서 업데이트를   시도한다.

세션A:(SID = 27)
SQL> update tx_itl_test set id = 3 where id = 3;
1 row updated.

세션B:(SID = 10)
SQL> update tx_itl_test set id = 4 where id = 4;
1 row upated.

세션C:(SID = 40)
SQL> update tx_itl_test set id = 5 where id = 5;
..... Wait ...................................................


세번째 업데이트를 수행한 10번 세션이 대기상태에 빠진다. 이 상태에서 V$LOCK 뷰를 통해 TX 락 경합이 어떻게 발생하는지 확인해보자

SQL> exec print_table('select * from v$lock where type = TX');
ADDR                           : C00000001EBA58B0
KADDR                         : C00000001EBA5A28
SID                              : 10
TYPE                             : TX
ID1                              : 65548
ID2                              : 58643
LMODE                         : 6    ? TX 락을 Exclusive하게 획득중
REQUEST                      : 0
CTIME                          : 33
BLOCK                         : 0
-----------------
ADDR                          : C00000001EB9DCE8
KADDR                        : C00000001EB9DE60
SID                             : 27
TYPE                           : TX
ID1                             : 131072
ID2                             : 68746
LMODE                        : 6    ? TX 락을 Exclusive하게 획득중
REQUEST                     : 0
CTIME                         : 43
BLOCK                        : 1
-----------------
ADDR                          : C00000001F1EFEE0
KADDR                        : C00000001F1EFF00
SID                             : 40
TYPE                           : TX
ID1                             : 131072
ID2                             : 68746
LMODE                        : 0
REQUEST                     : 4        <-- Shared 모드로 TX 락을 획득하기 위해 대기
CTIME                         : 14
BLOCK                        : 0

테스트) ITL 엔트리 부족에 의한 TX 락 경합

위의 테스트 결과를 분석하면 성공적으로 update를 수행한 27번 세션과 10번 세션은 자신의 트랜잭션에 해당하는 TX 락을 Exclusive하게 획득하는데 성공했음을 알 수 있다. 문제의 40번 세션은 최초에 Update를 수행한 27번 세션이 획득한 TX 락(ID1=131072, ID2=68746)을 Shared 모드(REQUEST=4)로 획득하기 위해 대기하고 있다. Unique Key 충돌에 의한 TX 락 경합과 ITL 엔트리 부족에 의한 TX 락 경합 사이에는 미묘한 차이점이 있다. Unique Key 충돌의 경우, 대기세션은 자신만의 TX 락을 Exclusive하게 획득한 상태에서 이전 세션이 획득한 TX 락을 Shared 모드로 획득하기 위해 대기한다. 반면 ITL 부족의 경우, 대기세션은 자신만의 TX 락을 획득하기 전에 이전 세션이 획득한 TX 락을 Shared 모드로 획득하기 위해서 대기한다. 이러한 차이는 블록을 변경하기 전에 먼저 ITL 엔트리를 등록해야 하는 데서 비롯된다. ITL 엔트리 부족에 따른 TX 락 경합 현상은 일반적인 상황에서는 잘 생기지 않는다. 동시에 수십 ~ 수백 개의 세션이 하나의 블록에 대해 서로 다른 로우를 변경하는 경우는 매우 드물기 때문이다. 다만, Row Chaining이나 Row Migration이 발생한 로우의 경우 하나의 로우를 업데이트할 때 여러 개의 블록에 대해 각각 ITL 엔트리를 할당해야 하므로 이로 인해 ITL엔트리 부족에 의한 TX 락 경합이 발생할 확률이 높아진다.

[편집]Parameter & Wait Time

[편집]Wait Parameters

  • P1 : Enqueue 정보
  • P2 : usn<<16 | slot
  • P3 : sequence

[편집]Wait Time

enqueue 대기이벤트와 동일하다. 최대 3초까지 기다린다. 만일 TX 락을 획득하기 못하면 획득할 때까지 대기한다

[편집]Check Point & Solution

[편집]높은 INITTRANS 속성 부여

높은 INITRANS 값으로 테이블을 생성하는 것이 ITL 공간 부족에 따른 TX 락 경합 현상을 해결하는 일반적인 방법이다. 더욱 중요한 것은 잘못된 어플리케이션 설계로 불필요한 경합이 발생되는 것인지 판단하는 것이며, 잘못된 설계에 의한 것이라면 어플리케이션을 수정하는 것만이 유일한 해결책이다.

V$SEGMENT_STATISTICS 뷰를 이용하면 어떤 세그먼트에 대해서 ITL 부족에 의한 경합이 많이 발생하는지 확인할 수 있다. STATISTIC_NAME = 'ITL waits' 조건을 이용하면 어떤 세그먼트에 대해 ITL 부족 문제가 많이 발생했는지 알 수 있다.

[편집]Event Tip

[편집]Analysis Case


출처 : http://wiki.ex-em.com/index.php/Enq:_TX_-_allocate_ITL_entry

fast commit

오라클은 기본적으로 fast commit을 지원합니다. 트랜잭션이
발생하게 되면 fast commit을 통해서 데이터파일에 즉각 반영하는
것이 아니라, online redo log에 먼저 redo log buffer의
반영을 합니다.
log switch나 checkpoint가 일어났을 때 또는 DBWR프로세스가 
데이터파일에 쓰야만 하는 때(free buffer 부족등) 데이터파일에 
메모리에 있는 내용을 기록하게 됩니다. 물론 commit을 안했다고 
해서 데이터파일에 기록을 안한다는 것은 아닙니다. checkpoint가
일어나게 되면 또는 DBWR프로세스가 작동하게 되면 commit을 하지 
않은 데이터도 데이터파일에 쓰겠죠. 이 두가지에 차이에 대해서는 아래에 
설명을 해봅니다.

commit을 하게 되면 LGWR 프로세스가 online redo log file에 
redo log buffer에 있는 redo log entry를 write를 하게 됩니다. 
이 write작업이 끝나야 commit 이후 프롬프트가 떨어집니다. 

즉 commit의 프롬프트가 떨어지지 않았는데 redo log에 기록을하지
않았다는 것은 있을 수가 없지요.
그렇다면.. 트랜잭션이 많다면 어떻게 될까요? 이 때에는 
commit이 일어나서 write를 하기 전에 LGWR프로세스가 다른 경우에
의해서 online redo log에 redo log buffer를 write를 한 것입니다. 
그러므로 commit이라고 명령을 하는 것이 오래 걸리지 않습니다.

A->B로 변경후 commit을 하였다고 한다면..
LGWR프로세스가 online redo log에는 redo log buffer에 있는
변경정보를 redo log file에 write를 하였으나 DBWR프로세스가 
데이터파일에는 write를 하지 않을 수 있습니다. 그러므로 A->B로 변경은 
하였으나 데이터파일에는 A라는 값이 그대로 있을 수 있겠죠.
이 때에 DB를 abort로 내리고 DB를 재기동하면 smon 프로세스는 
recovery를 수행합니다. 이 때에 online redo log에서 commit되었으나
데이터파일에 반영되지 않은 데이터를 메모리에 올려서 반영하는 작업을
하게 됩니다. 이것을 rollforward라고 합니다.

한편으로 update를 C->D로 변경을 하였다면.. C라는 데이터를 데이터파일에서
읽어와서 rollback image에 C라는 값을 두고, 원본이미지를 D로 변경합니다.

만약 트랜잭션이 많아서 free buffer가 부족하거나 checkpoint가 일어나거나
하게 되면 DBWR프로세스가 데이터파일에 쓰겠죠. 그런데.. 이 때에
C라는 기존 원본은 undo tablespace로 데이터가 들어가고, D라는 변경된
값은 데이터파일에 write를 하게 됩니다.

즉 commit을 하지 않은 데이터가 있으나 DBWR프로세스가 메모리에 있는
데이터를 데이터파일에 저장할 수 있습니다.
이 때에 DB를 abort로 내리고 다시 올리면 smon프로세스는 앞에서 말씀드린
rollforward를 하기도 하지만, rollback도 하게 됩니다. 이 때에는 commit되지
undo에서 commit되지 않은 데이터를 메모리로 올리고, 데이터파일에
undo데이터를 데이터파일에 write를 하게 됩니다. 이것이 바로 rollback입니다.
undo에는 원본이미지, 데이터파일에는 변경이미지가 있으나 commit을 하지
않았으니 undo에 있는 원본이미지를 데이터파일에 변경이미지에 엎어씌워야
겠지요..




Delayed Block Cleanout

Delayed block cleanout의 개념을 이해하려면 우선 오라클에서 사용하는 몇가지 용어에 대해 알아야 한다.

Cleanout 또는 block cleanout이란 블록에 설정된 로우 레벨 락을 해제(Cleanout)한다는 의미이다. Cleanout이 발생하면 로우 레벨 락이 해제되고 ITL 정보(SCN, Flag, Lock Byte 등)가 갱신된다.

Fast commit이란 커밋 시점에 모든 블록에 대해 cleanout을 수행하지 않는다는 것을 의미한다. 오라클은 성능상의 문제로 변경된 데이터 블록들 중 버퍼 캐시에 올라와 있는 일부 블록들에 대해서만 cleanout을 수행한다. Fast Commit이 발생하는 경우, 변경되는 정보의 량을 최소화하기 위해 ITL 정보에서 Flag와 SCN 정보만 변경되고 lock byte 정보는 변경되지 않는다. Lock byte 정보는 트랜잭션에 의해 변경된 모든 로우에 저장되므로 변경해야 할 데이터의 양이 많기 때문이다. Fast commit 기법은 변경된 일부 데이터 블록들의 헤더에 대해서만 변경 작업을 수행하기 때문에 리두 데이터가 생성되지 않고, 커밋 마크(Commit Mark)만이 리두에 저장된다. 수백만 건의 데이터를 변경한 후에 커밋을 수행하는 경우에도 매우 빠른 속도로 커밋 처리가 되는 것은 이러한 기법 덕분이다.

Delayed block cleanout이란 변경된 데이터 블록들 중 Fast commit에 의해 cleanout 되지 않은 블록들을 나중에(Delayed) cleanout 처리한다는 의미이다. Delayed block cleanout는 다음 번에 해당 블록을 스캔하는 프로세스에 의해 수행된다. Delayed block cleanout이 발생하는 경우 순수한 Select 작업인 경우에도 cleanout 작업 자체에 대한 리두 데이터가 생성될 수 있다.

커밋 수행(Fast commit)에 의해 cleanout이 수행되면 cleanout이 발생한 블록 수만큼 commit cleanouts 통계값이 증가한다. Cleanout을 수행하는 도중 에러가 발생하면 에러의 발생 원인에 따라 commit cleanout failures: xxxx 류의 통계값이 증가한다. Cleanout 수행에 성공한 경우에는 commit cleanouts successfully completed 통계값이 증가한다. 각 값들은 다음과 같은 관계를 따른다.

commit cleanouts = commit cleanouts successfully completed + 
Sum of (commit cleanout failures: xxxx)

user commits 통계값이 사용자가 커밋을 수행한 회수를 나타내는 반면 commit cleanouts 는 커밋에 의한 cleanout이 발생한 블록 수를 나타낸다는 사실에 유의하자.

Fast commit이 발생하면 ITL의 flag 값이 “U”(Upper Bound Commit)로 수정되고 SCN이 할당된다. 하지만 블록 내의 개별 로우의 lock byte값은 변경되지 않는다. 나중에 해당 블록을 다른 프로세스가 변경하는 경우에 flag 값이 “C”(Commit) 로 변경되고 블록 내의 개별 로우의 lock byte값도 정리(0의 값)된다.


출처 : http://wiki.ex-em.com/index.php/Delayed_block_cleanout 

[11g] flashback table example

FLASHBACK TABLE

Purpose

Use the FLASHBACK TABLE statement to restore an earlier state of a table in the event of human or application error. The time in the past to which the table can be flashed back is dependent on the amount of undo data in the system. Also, Oracle Database cannot restore a table to an earlier state across any DDL operations that change the structure of the table.

Note:

Oracle strongly recommends that you run your database in automatic undo mode by leaving the UNDO_MANAGEMENT initialization parameter set to AUTO, which is the default. In addition, set the UNDO_RETENTION initialization parameter to an interval large enough to include the oldest data you anticipate needing. For more information refer to the documentation on the UNDO_MANAGEMENT and UNDO_RETENTIONinitialization parameters.

You cannot roll back a FLASHBACK TABLE statement. However, you can issue another FLASHBACK TABLE statement and specify a time just prior to the current time. Therefore, it is advisable to record the current SCN before issuing a FLASHBACK TABLE clause.

See Also:

Prerequisites

To flash back a table to an earlier SCN or timestamp, you must have either the FLASHBACK object privilege on the table or the FLASHBACK ANY TABLE system privilege. In addition, you must have the SELECTINSERTDELETE, and ALTER object privileges on the table.

Row movement must be enabled for all tables in the Flashback list unless you are flashing back the table TO BEFORE DROP. That operation is called a flashback dropoperation, and it uses dropped data in the recyclebin rather than undo data. Refer to row_movement_clause for information on enabling row movement.

To flash back a table to a restore point, you must have the SELECT ANY DICTIONARY or FLASHBACK ANY TABLE system privilege or the SELECT_CATALOG_ROLE role.

To flash back a table to before a DROP TABLE operation, you need only the privileges necessary to drop the table.

Syntax

flashback_table::=

Description of flashback_table.gif follows
Description of the illustration flashback_table.gif

Semantics

During an Oracle Flashback Table operation, Oracle Database acquires exclusive DML locks on all the tables specified in the Flashback list. These locks prevent any operations on the tables while they are reverting to their earlier state.

The Flashback Table operation is executed in a single transaction, regardless of the number of tables specified in the Flashback list. Either all of the tables revert to the earlier state or none of them do. If the Flashback Table operation fails on any table, then the entire statement fails.

At the completion of the Flashback Table operation, the data in table is consistent with table at the earlier time. However, FLASHBACK TABLE TO SCN or TIMESTAMP does not preserve rowids, and FLASHBACK TABLE TO BEFORE DROP does not recover referential constraints.

Oracle Database does not revert statistics associated with table to their earlier form. Indexes on table that exist currently are reverted and reflect the state of the table at the Flashback point. If the index exists now but did not yet exist at the Flashback point, then the database updates the index to reflect the state of the table at the Flashback point. However, indexes that were dropped during the interval between the Flashback point and the current time are not restored.

schema

Specify the schema containing the table. If you omit schema, then the database assumes the table is in your own schema.

table

Specify the name of one or more tables containing data you want to revert to an earlier version.

Restrictions on Flashing Back Tables This statement is subject to the following restrictions:

  • Flashback Table operations are not valid for the following type objects: tables that are part of a cluster, materialized views, Advanced Queuing (AQ) tables, static data dictionary tables, system tables, remote tables, object tables, nested tables, or individual table partitions or subpartitions.

  • The following DDL operations change the structure of a table, so that you cannot subsequently use the TO SCN or TO TIMESTAMP clause to flash the table back to a time preceding the operation: upgrading, moving, or truncating a table; adding a constraint to a table, adding a table to a cluster; modifying or dropping a column; changing a column encryption key; adding, dropping, merging, splitting, coalescing, or truncating a partition or subpartition (with the exception of adding a range partition).

TO SCN Clause

Specify the system change number (SCN) corresponding to the point in time to which you want to return the table. The expr must evaluate to a number representing a valid SCN.

TO TIMESTAMP Clause

Specify a timestamp value corresponding to the point in time to which you want to return the table. The expr must evaluate to a valid timestamp in the past. The table will be flashed back to a time within approximately 3 seconds of the specified timestamp.

TO RESTORE POINT Clause

Specify a restore point to which you want to flash back the table. The restore point must already have been created.

See Also:

CREATE RESTORE POINT for information on creating restore points

ENABLE | DISABLE TRIGGERS

By default, Oracle Database disables all enabled triggers defined on table during the Flashback Table operation and then reenables them after the Flashback Table operation is complete. Specify ENABLE TRIGGERS if you want to override this default behavior and keep the triggers enabled during the Flashback process.

This clause affects only those database triggers defined on table that are already enabled. To enable currently disabled triggers selectively, use the ALTER TABLE ...enable_disable_clause before you issue the FLASHBACK TABLE statement with the ENABLE TRIGGERS clause.

TO BEFORE DROP Clause

Use this clause to retrieve from the recycle bin a table that has been dropped, along with all possible dependent objects. The table must have resided in a locally managed tablespace other than the SYSTEM tablespace.

See Also:

You can specify either the original user-specified name of the table or the system-generated name Oracle Database assigned to the object when it was dropped.

  • System-generated recycle bin object names are unique. Therefore, if you specify the system-generated name, then the database retrieves that specified object.

    To see the contents of your recycle bin, query the USER_RECYCLEBIN data dictionary review. You can use the RECYCLEBIN synonym instead. The following two statements return the same rows:

    SELECT * FROM RECYCLEBIN;
    SELECT * FROM USER_RECYCLEBIN;
    
  • If you specify the user-specified name, and if the recycle bin contains more than one object of that name, then the database retrieves the object that was moved to the recycle bin most recently. If you want to retrieve an older version of the table, then do one of these things:

    • Specify the system-generated recycle bin name of the table you want to retrieve.

    • Issue additional FLASHBACK TABLE ... TO BEFORE DROP statements until you retrieve the table you want.

Oracle Database attempts to preserve the original table name. If a new table of the same name has been created in the same schema since the original table was dropped, then the database returns an error unless you also specify the RENAME TO clause.

RENAME TO Clause Use this clause to specify a new name for the table being retrieved from the recycle bin.

Notes on Flashing Back Dropped Tables The following notes apply to flashing back dropped tables:

  • Oracle Database retrieves all indexes defined on the table retrieved from the recycle bin except for bitmap join indexes. (Bitmap join indexes are not put in the recycle bin during a DROP TABLE operation, so cannot be retrieved.)

  • The database also retrieves all triggers and constraints defined on the table except for referential integrity constraints that reference other tables.

    The retrieved indexes, triggers, and constraints have recycle bin names. Therefore it is advisable to query the USER_RECYCLEBIN view before issuing a FLASHBACK TABLE... TO BEFORE DROP statement so that you can rename the retrieved triggers and constraints to more usable names.

  • When you drop a table, all materialized view logs defined on the table are also dropped but are not placed in the recycle bin. Therefore, the materialized view logs cannot be flashed back along with the table.

  • When you drop a table, any indexes on the table are dropped and put into the recycle bin along with the table. If subsequent space pressures arise, then the database reclaims space from the recycle bin by first purging indexes. In this case, when you flash back the table, you may not get back all of the indexes that were defined on the table.

  • You cannot flash back a table if it has been purged, either by a user or by Oracle Database as a result of some space reclamation operation.

Examples

Restoring a Table to an Earlier State: Examples The examples below create a new table, employees_test, with row movement enabled, update values within the new table, and issue the FLASHBACK TABLE statement.

Create table employees_test, with row movement enabled, from table employees of the sample hr schema:

CREATE TABLE employees_test 
  AS SELECT * FROM employees;

As a benchmark, list those salaries less than 2500:

SELECT salary
  FROM employees_test
  WHERE salary < 2500;

    SALARY
----------
      2400
      2200
      2100
      2400
      2200

Note:

To allow time for the SCN to propagate to the mapping table used by the FLASHBACK TABLE statement, wait a minimum of 5 minutes prior to issuing the following statement. This wait would not be necessary if a previously existing table were being used in this example.

Enable row movement for the table:

ALTER TABLE employees_test
   ENABLE ROW MOVEMENT;

Issue a 10% salary increase to those employees earning less than 2500:

UPDATE employees_test
  SET salary = salary * 1.1
  WHERE salary < 2500;

5 rows updated.
COMMIT;

As a second benchmark, list those salaries that remain less than 2500 following the 10% increase:

SELECT salary
  FROM employees_test
  WHERE salary < 2500;

    SALARY
----------
      2420
      2310
      2420
  

Restore the table employees_test to its state prior to the current system time. The unrealistic duration of 1 minute is used so that you can test this series of examples quickly. Under normal circumstances a much greater interval would have elapsed.

FLASHBACK TABLE employees_test
  TO TIMESTAMP (SYSTIMESTAMP - INTERVAL '1' minute);

List those salaries less than 2500. After the FLASHBACK TABLE statement issued above, this list should match the list in the first benchmark.

SELECT salary
  FROM employees_test
  WHERE salary < 2500;

    SALARY
----------
      2400
      2200
      2100
      2400
      2200

Retrieving a Dropped Table: Example If you accidentally drop the pm.print_media table and want to retrieve it, then issue the following statement:

FLASHBACK TABLE print_media TO BEFORE DROP;

If another print_media table has been created in the pm schema, then use the RENAME TO clause to rename the retrieved table:

FLASHBACK TABLE print_media TO BEFORE DROP RENAME TO print_media_old;

If you know that the employees table has been dropped multiple times, and you want to retrieve the oldest version, then query the USER_RECYLEBIN table to determine the system-generated name, and then use that name in the FLASHBACK TABLE statement. (System-generated names in your database will differ from those shown here.)

SELECT object_name, droptime FROM user_recyclebin 
   WHERE original_name = 'PRINT_MEDIA';

OBJECT_NAME                    DROPTIME
------------------------------ -------------------
RB$$45703$TABLE$0              2003-06-03:15:26:39
RB$$45704$TABLE$0              2003-06-12:12:27:27
RB$$45705$TABLE$0              2003-07-08:09:28:01

http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_9012.htm#SQLRF01802