1つのOracleデータベースに複数のシステムのデータが入っていて、あるシステムだけ昨日の夜間バッチが走る前の状態に戻したいといったケースで、関係ない表領域はオンラインのままで一部の表領域だけ巻き戻すことができるか検証してみる。システム単位で表領域が分かれていることを前提とする。
と思って検証しようとしたが、単純にリストア・リカバリではダメだということがわかった。
補助データベース、要するにもう一つデータベースを作って、そこで希望の時点までリカバリして、補助データベースからデータをターゲットデータベースにコピーするといったことになるみたい。ちょっとめんどうだな〜
DB2 や SQLServer は1インスタンス内に複数のデータベースを作成できるけど、Oracle は1インスタンスに1データベース。1台のマシンで複数のインスタンスを動かすとメモリが大量に必要になるし、こういうケースでは data pump でバックアップとっておいたほうが良さそう。ただし、バックアップとった時点まで戻るし、アーカイブログ使って任意の時点に戻したりすることはできない。
単純に一部の表領域だけ夜間にとったコールドバックアップの時点に戻したい場合は、データファイルのSCNを書き換えてリストア。。。と思ったけど、データベースがオンラインのままだと SCN がどんどん進むから無理か。。。
環境
SQL> !cat /etc/issue CentOS release 5.3 (Final) Kernel \r on an \m SQL> !uname -a Linux centos51 2.6.18-128.el5 #1 SMP Wed Jan 21 10:44:23 EST 2009 i686 i686 i386 GNU/Linux SQL> select * from v$version; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod PL/SQL Release 10.2.0.4.0 - Production CORE 10.2.0.4.0 Production TNS for Linux: Version 10.2.0.4.0 - Production NLSRTL Version 10.2.0.4.0 - Production
検証結果
- 表領域HIDEBUを作成する。
$ sqlplus / as sysdba SQL> create tablespace hidebu datafile '/u01/app/oracle/oradata/orcl/hidebu01.dbf' size 5m; SQL> alter user scott quota unlimited on hidebu; SQL> select tablespace_name, status from dba_tablespaces; TABLESPACE_NAME STATUS ------------------------------ --------- SYSTEM ONLINE UNDOTBS ONLINE SYSAUX ONLINE TEMP ONLINE USERS ONLINE HIDEBU ONLINE
- コールドバックアップをとる。
SQL> shutdown immediate SQL> exit $ cd /u01/app/oracle/oradata/orcl $ cp -p hidebu01.dbf hidebu01.dbf.org $ ls -l hidebu* -rw-r----- 1 oracle oinstall 5251072 10月 28 21:08 hidebu01.dbf -rw-r----- 1 oracle oinstall 5251072 10月 28 21:08 hidebu01.dbf.org
- データベースをオープンする。
$ sqlplus / as sysdba
SQL> startup
- USERS表領域とHIDEBU表領域のデータを更新する。
SQL> CREATE TABLE "SCOTT"."EMP1" ( "EMPNO" NUMBER(4,0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4,0), "HIREDATE" DATE, "SAL" NUMBER(7,2), "COMM" NUMBER(7,2), "DEPTNO" NUMBER(2,0), CONSTRAINT "PK_EMP1" PRIMARY KEY ("EMPNO") ) TABLESPACE "USERS" / SQL> CREATE TABLE "SCOTT"."EMP2" ( "EMPNO" NUMBER(4,0), "ENAME" VARCHAR2(10), "JOB" VARCHAR2(9), "MGR" NUMBER(4,0), "HIREDATE" DATE, "SAL" NUMBER(7,2), "COMM" NUMBER(7,2), "DEPTNO" NUMBER(2,0), CONSTRAINT "PK_EMP2" PRIMARY KEY ("EMPNO") ) TABLESPACE "HIDEBU" / SQL> select table_name, tablespace_name from dba_tables where owner = 'SCOTT'; TABLE_NAME TABLESPACE_NAME ------------------------------ ------------------------------ EMP2 HIDEBU EMP1 USERS SQL> begin for i in 1..100 loop insert into scott.emp1 (empno, ename) values (i,'neo'); end loop; end; / SQL> begin for i in 1..100 loop insert into scott.emp2 (empno, ename) values (i,'smith'); end loop; end; / SQL> select count(1) from scott.emp1; COUNT(1) ---------- 100 SQL> select count(1) from scott.emp2; COUNT(1) ---------- 100 SQL> commit;
- HIDEBU 表領域を元に戻す。
SQL> alter tablespace hidebu offline; SQL> !mv hidebu01.dbf hidebu01.dbf.mod SQL> !cp -p hidebu01.dbf.org hidebu01.dbf SQL> select FILE#,CHECKPOINT_CHANGE#, LAST_CHANGE# from v$datafile; FILE# CHECKPOINT_CHANGE# LAST_CHANGE# ---------- ------------------ ------------ 1 220266 2 220266 3 220266 4 220266 5 220540 220540 SQL> select scn_to_3timestamp(220540) as timestamp from dual; --イマココ。うまくいかないので調査中。。。どうやらこの方法では無理だということに気づき、終了〜 SQL> RECOVER TABLESPACE HIDEBU UNTIL TIME '28-OCT-09 10.11.51.000000000 PM28-OCT-09 10.11.51.000000000 PM'; SQL> alter tablespace hidebu online; SQL> select tablespace_name,status from user_tablespaces;