この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。遅れてきたAWS新人、@yokatsukiです。
Amazon RDS for MySQLにはデータベースの読み取り専用コピーを作成する機能"Read Replica"が提供されています(参考リンク)。 しかし、Amazon RDS for Oracle(以下RDS Oracle)にはRead Replicaが提供されていません。そこで今回はこの代わりにマテリアライズド・ビューを使ってみようという話を致します。
今回のエントリはOracleデータベース管理としては割と基本的な内容になります。しかしネットサービス構成部分にRDS特有な点がありますので、"3.ネットサービスの設定とデータベースリンクの作成"はご一読頂くと参考になるのではと思います。
検証
0.環境概要
- マスタ環境、レプリカ環境
- Amazon RDS for Oracle SE One 11.2.0.2.v7(license-included) x2
Oracle製品はEdition毎に機能制限があるのですが、読み取り専用マテリアライズド・ビューであればStandard Editionでも提供されています。詳細は下記ページ内の"統合"の項をご覧ください。
エディション別の使用可能な機能 - Oracle Databaseライセンス情報 11gリリース2 (11.2) B56284-08
1.ユーザの作成
Oracle RDSのMaster Userで以下のSQL文を発行し、ユーザを作成します。
1-1.マスタ側
CREATE USER master
IDENTIFIED BY xxxx
QUOTA UNLIMITED ON users;
GRANT CONNECT, RESOURCE
TO master;
1-2.レプリカ側
CREATE USER replica
IDENTIFIED BY xxxx
QUOTA UNLIMITED ON users;
GRANT CONNECT, RESOURCE,
CREATE DATABASE LINK,
CREATE MATERIALIZED VIEW
TO replica;
ちょっと余談になりますが、11gでは事前定義済みのロールに含まれる権限が大変弱く、CONNECTロールとRESOURCEロールを与えてようやく一般ユーザとして最低限の事ができるようになっています。気になった方は、以下のSQL文を発行してみてください。
SELECT * FROM DBA_SYS_PRIVS
WHERE GRANTEE IN ('CONNECT', 'RESOURCE')
ORDER BY 1, 2;
2.テーブルの作成
マスタ側でデータベースユーザmasterにログオンし、今回の検証で使用する簡単なテーブルtestを作成します。
2-1.マスタ側
CONNECT master/xxxx
CREATE TABLE test(
ID NUMBER(2) PRIMARY KEY,
DATA VARCHAR2(8)
);
INSERT INTO test VALUES(1, 'aaaaaaaa');
INSERT INTO test VALUES(2, 'bbbbbbbb');
COMMIT;
3.ネットサービスの設定とデータベースリンクの作成
一般的には、データベースリンクを作成する際、まずOracleがインストールされたディレクトリ$ORACLE_HOME/network/admin以下のネットワーククライアント設定ファイルtnsnames.oraを編集して、以下の様に接続文字列(2行目以降の文字列)とネットサービス名(1行目)を加えます。
mynetservice = <-ネットサービス名(接続文字列に付けたエイリアス)
(DESCRIPTION=
(ADDRESS=
(PROTOCOL=TCP) <-通信プロトコル
(HOST=master.xxxxxx.ap-northeast-1.rds.amazonaws.com) <-DB稼働ホスト名
(PORT=1521) <-リスナー稼働ポート番号
)
(CONNECT_DATA=
(SID=orcl) <-接続インスタンス名
)
)
その後、ネットサービス名+アカウント情報を持つデータベースリンクを以下の様なSQL文で作成します。
CREATE DATABASE LINK mylink
CONNECT TO userxx IDENTIFIED BY xxxx
USING 'mynetservice'; <-ネットサービス名
ところがRDSでは、データベースが動いている仮想マシンへのOSレベルでのアクセスを禁じています。ということは、tnsnames.oraの編集ができない為、ネットサービスの構成ができない、ということになります。
しかしご安心ください。これには解決法があって、ネットサービス名の代わりにダイレクトに接続文字列を記述すれば良いのです。この方法は、下記AWSのドキュメントにも例文として記載されています。
Importing Data Into Oracle on Amazon RDS
3-1.レプリカ側
CONNECT replica/xxxx
CREATE DATABASE LINK mastersite
CONNECT TO master IDENTIFIED BY xxxx
USING '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<マスタのホスト名>)(PORT=1521))(CONNECT_DATA=(SID=<マスタのインスタンス名>)))';
データベースリンクの動作確認します。以下のSQL文を発行してみてください。
select * from master.test@mastersite;
マスタ側のtestテーブルが表示されればO.K.です。
ID DATA
---- --------
1 aaaaaaaa
2 bbbbbbbb
4.マテリアライズド・ビュー(MVIEW)の作成
簡単な例として、1分間隔で自動リフレッシュするMVIEW、replica_testを作成してみます。
4-1.マスタ側
CREATE MATERIALIZED VIEW LOG
ON test;
4-2.レプリカ側
CREATE MATERIALIZED VIEW replica_test
REFRESH FAST
START WITH SYSDATE
next sysdate + 1/24/60
AS
SELECT * FROM test@mastersite;
作成した後のMVIEWのリフレッシュ間隔については、以下のSQL文で確認することができます。
SELECT last_date, last_sec,
next_date, next_sec,
interval, what
FROM user_jobs;
LAST_DATE LAST_SEC NEXT_DATE NEXT_SEC INTERVAL WHAT
--------- -------- --------- -------- ------------------ -------------------------------------------------
14-07-13 18:33:08 14-07-13 18:34:08 sysdate + 1/24/60 dbms_refresh.refresh('"REPLICA"."REPLICA_TEST"');
5.マテリアライズド・ビュー(MVIEW)の動作確認
マスタ側テーブルtestが更新された後、1分後にはreplica_testが更新されている事を確認します。
5-1.マスタ側
UPDATE TEST SET DATA = 'eeeeeeee'
WHERE id = '1';
COMMIT;
5-2.レプリカ側
select * from replica_test;
以下の結果が表示されればO.K.です。
ID DATA
---- --------
1 eeeeeeee
2 bbbbbbbb
あとがき
読み取り専用マテリアライズド・ビュー(MVIEW)を使用して、Read Replicaもどきを作成しました。 今回の検証ではリフレッシュのタイミングについて触れませんでしたし、またリフレッシュの動作に関しても期待通り動かなかったりという話をちょくちょく耳にしています。使用する為には、事前に検証が必要に思いました。