Amazon RDS for Oracle – POINT IN TIME RECOVERY(テーブル)

前回の記事では、Amazon Relational Database Service (Amazon RDS) for Oracle において「データベース全体を指定した時点の状態に復元する」ことをテーマとした内容をご紹介いたしました。

今回は前回の記事に関連して、「特定のテーブルのみ指定した時点の状態に復元する」ことに着目し、前回と同様チュートリアルを中心に説明・紹介したいと思います。

特定テーブルに対する POINT IN TIME RECOVERY

「特定のテーブルのみ指定した時点の状態に復元する」ことは Oracle データベース標準搭載されている Flashback 機能でも実現は可能です。しかし Flashback 機能だけですべてのケースに対応できるわけではありません。

例えば、一定の時間が経過し UNDO が残っていない…といった状態では、Flashback 機能でカバーすることは困難になってしまいます。

このような場合、対処方法としてはテーブル単位で Amazon RDS for OracleのPOINT IN TIME RECOVERY を実施する方法が挙げられます。

チュートリアルの事前準備

  • Amazon RDS for Oracle
  • データベースへの接続用端末を一台
  • 周辺端末、ツール

チュートリアルを開始する前に、Amazon RDS for Oracle を用意し、端末に Oracle クライアントをインストールしてください。

今回の例ではテーブル等のデータベースの内容を確認するため、SQL 発行ツールは Oracle SQL*Plus、端末は Windows を利用しています。

チュートリアル

チュートリアルは以下2つの構成(コンポーネント)で実現しています。

  •  AWS RDS for Oracle
  •  Amazon Elastic Compute Cloud (Amazon EC2)

※データベースクライアントツールをインストール済み

1.Amazon RDS for Oracle を作成
  • 最小構成で問題ありません。
  • データベース作成には10分以上要する場合があります。
2.Oracle データベースへの接続

データベース接続する必要なホスト名、ポート番号、サービス名、データベースユーザー名、パスワードを入力し、Oracleクライアントツールで接続します。

3.Oracle データベーステーブル作成およびデータ投入

このチュートリアルでは、復元できたかを確認しやすいように、一秒間隔で「現在の時刻の文字列」と「現在の時刻のタイムスタンプ」をデータとしてテーブルに挿入しています。

テーブル名「Table01s」の作成SQL文サンプル

create table "Table01s"
(Id NUMBER(19) generated by default on null as identity 
 constraint "PK_Table01s" primary key,
 TableName NVARCHAR2(2000),
 InsertDateTimeString NVARCHAR2(2000),
 InsertDateTime TIMESTAMP(7) not null
);

テーブル名「Table02s」の作成SQL文サンプル

create table "Table02s"
(Id NUMBER(19) generated by default on null as identity 
 constraint "PK_Table02s" primary key,
 TableName NVARCHAR2(2000),
 InsertDateTimeString NVARCHAR2(2000),
 InsertDateTime TIMESTAMP(7) not null
);

一秒間隔でデータを挿入するC# コードのサンプル

// loop 1200 time
for( int i = 0 ; i < 1200 ; i++ )
{
 //insert into Table01s
 await OracleDbConnection.Table01s.AddAsync( new Table01() );
 //insert into Table02s
 await OracleDbConnection.Table02s.AddAsync( new Table02() );
 //COMMIT
 await OracleDbConnection.SaveChangesAsync();

 //Sleep one Second
 Thread.Sleep(1000);
}
4.挿入されたデータを確認(一部)
select * from "Table01s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table01    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4830807 
  113  Table01    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5250651 
  114  Table01    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5660862
  115  Table01    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6071142
  116  Table01    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6745007
  117  Table01    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7155107
  118  Table01    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7575129
  119  Table01    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7975582
  120  Table01    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8375971
  121  Table01    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9284349 ★
  122  Table01    8/15/2019 10:30:00 AM   2019-08-15 10:30:00.9704357 
  123  Table01    8/15/2019 10:30:02 AM   2019-08-15 10:30:02.0124255
  124  Table01    8/15/2019 10:30:03 AM   2019-08-15 10:30:03.0544300
  125  Table01    8/15/2019 10:30:04 AM   2019-08-15 10:30:04.0954498
  126  Table01    8/15/2019 10:30:05 AM   2019-08-15 10:30:05.1716260
  127  Table01    8/15/2019 10:30:06 AM   2019-08-15 10:30:06.2136436
  128  Table01    8/15/2019 10:30:07 AM   2019-08-15 10:30:07.2585555
  129  Table01    8/15/2019 10:30:08 AM   2019-08-15 10:30:08.2995733
  130  Table01    8/15/2019 10:30:09 AM   2019-08-15 10:30:09.3405906
  131  Table01    8/15/2019 10:30:10 AM   2019-08-15 10:30:10.3846636

select count(*) from "Table01s";

count(*)
--------
  1200

select * from "Table02s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table02    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4832277 
  113  Table02    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5252166 
  114  Table02    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5662312
  115  Table02    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6072965
  116  Table02    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6746576
  117  Table02    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7156602
  118  Table02    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7576595
  119  Table02    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7977028
  120  Table02    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8377429
  121  Table02    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9285832 ★
  122  Table02    8/15/2019 10:30:00 AM   2019-08-15 10:30:00.9705783
  123  Table02    8/15/2019 10:30:02 AM   2019-08-15 10:30:02.0125774
  124  Table02    8/15/2019 10:30:03 AM   2019-08-15 10:30:03.0545819
  125  Table02    8/15/2019 10:30:04 AM   2019-08-15 10:30:04.0956067
  126  Table02    8/15/2019 10:30:05 AM   2019-08-15 10:30:05.1717714
  127  Table02    8/15/2019 10:30:06 AM   2019-08-15 10:30:06.2137886
  128  Table02    8/15/2019 10:30:07 AM   2019-08-15 10:30:07.2587005
  129  Table02    8/15/2019 10:30:08 AM   2019-08-15 10:30:08.2997199
  130  Table02    8/15/2019 10:30:09 AM   2019-08-15 10:30:09.3407368
  131  Table02    8/15/2019 10:30:10 AM   2019-08-15 10:30:10.3848197

select count(*) from "Table02s";

count(*)
--------
  1200
5.POINT IN TIME RECOVERY(データベース全体) 実行

RDSデータベースを選択 > アクション > 特定時点への復元を選択
POINT IN TIME RECOVERY 実行

 

復元したい時刻を選択し、データベースサーバ構成を最初から入力してください。
以下の画面では2019年8月15日10:30:00 UTC+9に設定しています。
DBインスタンスの起動

6.POINT IN TIME RECOVERY 後のデータ確認
select * from "Table01s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table01    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4830807 
  113  Table01    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5250651 
  114  Table01    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5660862
  115  Table01    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6071142
  116  Table01    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6745007
  117  Table01    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7155107
  118  Table01    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7575129
  119  Table01    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7975582
  120  Table01    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8375971
  121  Table01    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9284349 ★

select * from "Table02s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table02    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4832277 
  113  Table02    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5252166 
  114  Table02    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5662312
  115  Table02    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6072965
  116  Table02    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6746576
  117  Table02    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7156602
  118  Table02    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7576595
  119  Table02    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7977028
  120  Table02    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8377429
  121  Table02    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9285832 ★

データベースが、復元時に指定した時刻である午前10時30分00秒の状態に戻ったことが確認できました。

ここまでは前回の記事の内容とほぼ同じですが、異なるポイントとしては、テーブルをもうひとつ用意して、同じデータをinsertしていることです。

7.データベースリンク作成

POINT IN TIME RECOVERY で新規作成されたデータベースから古いデータベースへのデータベースリンクを作成してください。

CREATE DATABASE LINK origin_db02
CONNECT TO admin IDENTIFIED BY xxxxxx
USING
'(DESCRIPTION =
  (ADDRESS =
    (PROTOCOL = TCP)
    (HOST = awscomt.chyqoeuzkmwi.ap-northeast-1.rds.amazonaws.com)
    (PORT = 1521)
  )
  (CONNECT_DATA =
    (SID = awscomt)
  )
)';
8.ダンプファイル作成

復元したいテーブルのみをダンプファイルへエクスポートします。
以下のサンプルは Table01s テーブルのみをダンプファイルへエクスポートするPL/SQLです。

DECLARE
 hdn1 NUMBER;
BEGIN
 hdn1 := DBMS_DATAPUMP.open( operation => 'EXPORT', job_mode => 'SCHEMA', job_name => null);
 DBMS_DATAPUMP.ADD_FILE( handle => hdn1, filename => 'expdb_tables.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
 DBMS_DATAPUMP.ADD_FILE( handle => hdn1, filename => 'expdb_tables.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
 DBMS_DATAPUMP.METADATA_FILTER( handle => hdn1, name => 'SCHEMA_EXPR', value => 'IN (''ADMIN'')');
 DBMS_DATAPUMP.METADATA_FILTER( handle => hdn1, name => 'NAME_EXPR', value => 'IN (''Table01s'')', object_path => 'TABLE');
 DBMS_DATAPUMP.START_JOB(hdn1);
END;
/
9.ダンプファイル転送

origin_db02データベースリンクを通してダンプファイルexpdb_tables.dmpを古いデータベースへ運搬します。

BEGIN
 DBMS_FILE_TRANSFER.PUT_FILE(
  source_directory_object    => 'DATA_PUMP_DIR',
  source_file_name        => 'expdb_tables.dmp',
  destination_directory_object => 'DATA_PUMP_DIR',
  destination_database     => 'origin_db02'
 );
END;
/
10.ダンプファイルでテーブル復元

TABLE_EXISTS_ACTIONの値をREPLACEに設定して、既存のテーブルの内容を上書きします。

DECLARE
 hdn1 NUMBER;
BEGIN
 hdn1 := DBMS_DATAPUMP.open( operation => 'IMPORT', job_mode => 'SCHEMA', job_name => null);
 DBMS_DATAPUMP.ADD_FILE( handle => hdn1, filename => 'tab1_copied.dmp', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_dump_file);
 DBMS_DATAPUMP.ADD_FILE( handle => hdn1, filename => 'imp.log', directory => 'DATA_PUMP_DIR', filetype => dbms_datapump.ku$_file_type_log_file);
 DBMS_DATAPUMP.METADATA_FILTER( handle => hdn1, name => 'SCHEMA_EXPR', value => 'IN (''ADMIN'')');
 DBMS_DATAPUMP.METADATA_FILTER( handle => hdn1, name => 'NAME_EXPR', value => 'IN (''Table01s'')', object_path => 'TABLE');
 DBMS_DATAPUMP.SET_PARAMETER(hdn1,'TABLE_EXISTS_ACTION','REPLACE');
 DBMS_DATAPUMP.START_JOB(hdn1);
END;
/
11.復元されたテーブル確認

テーブル「Tables01s」が復元される前には1200行あったデータが、121行となりました。
また、最新データの時刻も10時30分と表示されていることから、無事に復元が完了できたことが確認できます。

select * from "Table01s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table01    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4830807 
  113  Table01    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5250651 
  114  Table01    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5660862
  115  Table01    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6071142
  116  Table01    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6745007
  117  Table01    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7155107
  118  Table01    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7575129
  119  Table01    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7975582
  120  Table01    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8375971
  121  Table01    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9284349 ★

select count(*) from "Table01s";

count(*) 
--------
  121

 

テーブル「Table02s」はPOINT IN TIME RECOVERY前の状態を確認できます。

select * from "Table02s";

  Id  TableName   InsertDateTimeString   InsertDateTime
------- ------------- ------------------------- ----------------------------
                 :::
  112  Table02    8/15/2019 10:29:50 AM   2019-08-15 10:29:50.4832277 
  113  Table02    8/15/2019 10:29:51 AM   2019-08-15 10:29:51.5252166 
  114  Table02    8/15/2019 10:29:52 AM   2019-08-15 10:29:52.5662312
  115  Table02    8/15/2019 10:29:53 AM   2019-08-15 10:29:53.6072965
  116  Table02    8/15/2019 10:29:54 AM   2019-08-15 10:29:54.6746576
  117  Table02    8/15/2019 10:29:55 AM   2019-08-15 10:29:55.7156602
  118  Table02    8/15/2019 10:29:56 AM   2019-08-15 10:29:56.7576595
  119  Table02    8/15/2019 10:29:57 AM   2019-08-15 10:29:57.7977028
  120  Table02    8/15/2019 10:29:58 AM   2019-08-15 10:29:58.8377429
  121  Table02    8/15/2019 10:29:59 AM   2019-08-15 10:29:59.9285832 ★
  122  Table02    8/15/2019 10:30:00 AM   2019-08-15 10:30:00.9705783
  123  Table02    8/15/2019 10:30:02 AM   2019-08-15 10:30:02.0125774
  124  Table02    8/15/2019 10:30:03 AM   2019-08-15 10:30:03.0545819
  125  Table02    8/15/2019 10:30:04 AM   2019-08-15 10:30:04.0956067
  126  Table02    8/15/2019 10:30:05 AM   2019-08-15 10:30:05.1717714
  127  Table02    8/15/2019 10:30:06 AM   2019-08-15 10:30:06.2137886
  128  Table02    8/15/2019 10:30:07 AM   2019-08-15 10:30:07.2587005
  129  Table02    8/15/2019 10:30:08 AM   2019-08-15 10:30:08.2997199
  130  Table02    8/15/2019 10:30:09 AM   2019-08-15 10:30:09.3407368
  131  Table02    8/15/2019 10:30:10 AM   2019-08-15 10:30:10.3848197

select count(*) from "Table02s";

count(*)
--------
  1200

最後に、不要なデータベースとダンプファイルなどはお忘れなく削除してください。

まとめ

AWS RDS for Oracle の POINT IN TIME RECOVERY と Oracle のデータベースリンク、データポンプを組み合わせることで、指定したテーブルの復元に成功しました。

なお、復元したテーブルに外部キーで参照されている場合は、残念ながら別の対処方法を考える必要がありますのでご注意ください。

復元の流れ

 

タイトルとURLをコピーしました