트랜잭션 히스토리를 저장한 TRANS 테이블이 있다고 가정해 봅시다.
이 테이블은 TRANS_DATE를 기준으로 파티셔닝 되며, 각 분기별로 새로운 파티션이 생성됩니다. 가장 최근에 생성된 파티션은 매우 빈번하게 업데이트되지만, 분기가 마감되고 나면 해당 파티션에 대해 트랜잭션이 거의 발생하지 않으므로 파티션을 다른 위치로 옮겨도 무방합니다. 하지만 파티션을 이동하는 과정에서 테이블에 락(lock)이 걸리고 액세스가 차단될 수 있다는 것이 문제입니다. 그렇다면 가용성을 저해하지 않으면서 파티션을 이동할 수 있는 방법이 있을까요?
Oracle Database 10g Release 2는 단일 파티션에 대한 온라인 재구성 기능을 제공합니다. 이 작업은 전체 테이블을 대상으로 하는 온라인 재구성 작업과 동일한 방법으로 수행되지만 (DBMS_REDEFINITION 패키지가 사용됩니다), 그 내부 메커니즘에서는 차이가 있습니다. 일반 테이블은 소스 테이블에 대한 MV(materialized view)를 생성하는 방법으로 재구성되는 반면, 단일 파티션을 재구성할 때에는 “파티션을 교환하는(exchange partition)” 방법이 사용됩니다. 예를 통해 설명해 보겠습니다. TRANS 테이블의 구조가 아래와 같습니다:
SQL> desc trans Name Null? Type --------------------------------- -------- ------------------------- TRANS_ID NUMBER TRANS_DATE DATE TXN_TYPE VARCHAR2(1) ACC_NO NUMBER TX_AMT NUMBER(12,2) STATUS이 테이블은 다음과 같이 파티셔닝 되어 있습니다:
partition by range (trans_date) ( partition y03q1 values less than (to_date('04/01/2003','mm/dd/yyyy')), partition y03q2 values less than (to_date('07/01/2003','mm/dd/yyyy')), partition y03q3 values less than (to_date('10/01/2003','mm/dd/yyyy')), partition y03q4 values less than (to_date('01/01/2004','mm/dd/yyyy')), partition y04q1 values less than (to_date('04/01/2004','mm/dd/yyyy')), partition y04q2 values less than (to_date('07/01/2004','mm/dd/yyyy')), partition y04q3 values less than (to_date('10/01/2004','mm/dd/yyyy')), partition y04q4 values less than (to_date('01/01/2005','mm/dd/yyyy')), partition y05q1 values less than (to_date('04/01/2005','mm/dd/yyyy')), partition y05q2 values less than (to_date('07/01/2005','mm/dd/yyyy')) )일정 시간이 지난 후, Y03Q2 파티션을 저가형 스토리지로 구성된 다른 테이블스페이스(TRANSY03Q2)로 이동하려 합니다. 이 작업을 수행하려면, 먼저 테이블의 온라인 재정의가 가능한지 확인해야 합니다
begin dbms_redefinition.can_redef_table( uname => 'ARUP', tname => 'TRANS', options_flag => dbms_redefinition.cons_use_rowid, part_name => 'Y03Q2'); end; /아무런 결과가 출력되지 않으면, 정상적으로 확인이 된 것으로 간주합니다. 다음에는, 파티션의 데이터를 저장할 임시 테이블을 생성합니다:
create table trans_temp ( trans_id number, trans_date date, txn_type varchar2(1), acc_no number, tx_amt number(12,2), status varchar2(1) ) tablespace transy03q2 /TRANS 테이블이 영역(range)를 기준으로 파티셔닝 되어 있으므로, 임시 테이블은 파티셔닝 되지 않았음을 참고하시기 바랍니다. 이 테이블은 TRANSY03Q2 테이블스페이스 내에 생성됩니다. TRANS 테이블에 로컬 인덱스가 사용되고 있는 경우, 이 인덱스 또한 TRANS_TEMP 테이블에 생성해 주어야 합니다 (물론 파티셔닝은 하지 않습니다) 이제 재정의 작업을 수행할 준비가 완료되었습니다:
begin dbms_redefinition.start_redef_table( uname => 'ARUP', orig_table => 'TRANS', int_table => 'TRANS_TEMP', col_mapping => NULL, options_flag => dbms_redefinition.cons_use_rowid, part_name => 'Y03Q2'); end; /위의 호출 과정에서 참고할 만한 사항이 몇 가지 있습니다. 먼저, col_mapping 매개변수는 NULL로 설정되어 있습니다. 단일 파티션을 재정의하는 작업에서는 이 매개변수가 아무런 의미를 갖지 않습니다. 두 번째로 part_name 매개변수는 재정의 대상이 되는 파티션을 지정하는 용도로 사용됩니다. 세 번째로, COPY_TABLE_DEPENDENTS 매개변수가 사용되지 않고 있습니다. TRANS 테이블 자체에는 아무런 변화가 없으며 단지 파티션 만이 이동되는 것이므로 이 매개변수 또한 아무 의미가 없습니다. 테이블의 사이즈가 큰 경우에는 이 작업에 오랜 시간이 걸릴 수 있습니다. 따라서 동기화 작업을 수행해 주는 것이 좋습니다.
begin dbms_redefinition.sync_interim_table( uname => 'ARUP', orig_table => 'TRANS', int_table => 'TRANS_TEMP', part_name => 'Y03Q2'); end; /Finally, finish the process with
begin dbms_redefinition.finish_redef_table( uname => 'ARUP', orig_table => 'TRANS', int_table => 'TRANS_TEMP', part_name => 'Y03Q2'); end;이와 같이 하여, Y03Q2 파티션이 TRANSY03Q2 테이블스페이스에 생성되었습니다. 테이블에 글로벌 인덱스가 사용되고 있는 경우, 인덱스를 “UNUSABLE”로 마킹하고 rebuild 작업을 수행해야 합니다. 단일 파티션의 재정의 기능은 다른 테이블스페이스로 파티션을 이동하는 작업에서 유용하게 활용됩니다. 이러한 작업은 정보 생명주기 관리 차원에서 자주 사용되곤 합니다. 물론, 제약사항이 없는 것은 아닙니다. 재정의 작업이 수행되는 동안에는 파티셔닝 방법을 변경(예: range -> hash)할 수 없으며, 테이블의 구조를 변경할 수도 없습니다.
출처:오라클