概要
DBLINKとマテリアライズド・ビューを組み合わせたデータ同期について検証するために、DockerでOracleDBを2台立て、OracleDB間でのデータ移行とリフレッシュを試してみます。
実行環境
Dockerイメージの利用には自身でのDockerビルドが必要になりますが割愛します。
docker-composeを利用してDock上でOracleDBを2台立ち上げます。
ディレクトリoradata1、oradata2の所有者のユーザIDは54321にchownで変更しています。
oracle1が移行元、oracle2が移行先になります。
version: '3'
services:
oracle1:
image: oracle/database:19.3.0-ee
environment:
- ORACLE_SID=ORCLCDB1
- ORACLE_PWD=p@ssw0rd
- ORACLE_CHARACTERSET=AL32UTF8
ports:
- 11521:1521
- 15500:5500
volumes:
- ./oradata1:/opt/oracle/oradata
oracle2:
image: oracle/database:19.3.0-ee
environment:
- ORACLE_SID=ORCLCDB2
- ORACLE_PWD=p@ssw0rd
- ORACLE_CHARACTERSET=AL32UTF8
ports:
- 21521:1521
- 25500:5500
volumes:
- ./oradata2:/opt/oracle/oradata
作業概要
以下のシナリオで作業を進めます。
- (共通)ユーザ、スキーマ、表領域を用意
- (Oracle1)テーブルの作成とデータを挿入
- (Oracle2)データベースリンクの設定
- (Oracle1)マテリアライズド・ビューログを作成
- (Oracle2)マテリアライズド・ビューの作成
- (Oracle1)データの追加挿入確認
作業詳細
(共通)ユーザ、スキーマ、表領域を用意
(Oracle1)まずは、テーブルを作成する下準備をします。CDBに接続します。
sqlplus / as sysdba;
PDBに接続して表領域作成します。
ALTER SESSION SET CONTAINER = ORCLPDB1;
CREATE TABLESPACE TABLE_SPACE_MONSTER_GAME /*表領域名*/
DATAFILE '/opt/oracle/oradata/ORCLCDB1/ORCLPDB1/monster_game_1.dbf'
SIZE 100M /*サイズ*/
AUTOEXTEND OFF /*自動拡張*/
;
CREATE TEMPORARY TABLESPACE TEMP_SPACE_MONSTER_GAME /*表領域名*/
TEMPFILE '/opt/oracle/oradata/ORCLCDB1/ORCLPDB1/temp_monster_game_2.dbf'
SIZE 100M /*サイズ*/
;
ユーザ作成して権限付与します。
CREATE USER MONSTER_GAME
IDENTIFIED BY password123
DEFAULT TABLESPACE TABLE_SPACE_MONSTER_GAME
TEMPORARY TABLESPACE TEMP_SPACE_MONSTER_GAME
QUOTA 100M ON TABLE_SPACE_MONSTER_GAME
PROFILE DEFAULT
ACCOUNT UNLOCK
;
GRANT CREATE SESSION,
CREATE TABLE,
CREATE VIEW,
CREATE SEQUENCE,
CREATE TRIGGER,
CREATE SYNONYM,
UNLIMITED TABLESPACE TO MONSTER_GAME;
作成したユーザでPDBにログインします。
sqlplus MONSTER_GAME@//localhost:1521/ORCLPDB1
同様のことをOracle2でも実施します。
sqlplus / as sysdba;
ALTER SESSION SET CONTAINER = ORCLPDB1;
CREATE TABLESPACE TABLE_SPACE_MONSTER_GAME /*表領域名*/
DATAFILE '/opt/oracle/oradata/ORCLCDB2/ORCLPDB1/monster_game_1.dbf'
SIZE 100M /*サイズ*/
AUTOEXTEND OFF /*自動拡張*/
;
CREATE TEMPORARY TABLESPACE TEMP_SPACE_MONSTER_GAME /*表領域名*/
TEMPFILE '/opt/oracle/oradata/ORCLCDB2/ORCLPDB1/temp_monster_game_2.dbf'
SIZE 100M /*サイズ*/
;
CREATE USER MONSTER_GAME
IDENTIFIED BY password123
DEFAULT TABLESPACE TABLE_SPACE_MONSTER_GAME
TEMPORARY TABLESPACE TEMP_SPACE_MONSTER_GAME
QUOTA 100M ON TABLE_SPACE_MONSTER_GAME
PROFILE DEFAULT
ACCOUNT UNLOCK
;
GRANT CREATE SESSION,
CREATE TABLE,
CREATE VIEW,
CREATE SEQUENCE,
CREATE TRIGGER,
CREATE SYNONYM,
UNLIMITED TABLESPACE TO MONSTER_GAME;
(Oracle1)テーブルの作成とデータを挿入
同期したいテーブルを作成し適当にデータを入れておきます。
CREATE TABLE PLAYER(
NAME VARCHAR2(100) NOT NULL,
HP NUMBER(4, 0) NOT NULL,
STR NUMBER(3,0) NOT NULL,
DEF NUMBER(3,0) NOT NULL
);
INSERT INTO PLAYER VALUES ('MAGICIAN', 10, 10, 30);
INSERT INTO PLAYER VALUES ('THIEF', 20, 40, 30);
INSERT INTO PLAYER VALUES ('ASSASSIN', 20, 60, 30);
INSERT INTO PLAYER VALUES ('FIGHTER', 40, 30, 30);
(Oracle2)データベースリンクの設定
Oracle2にSYSでログインしてOracle2のMONSTER_GAMEに権限を追加します。
GRANT CREATE DATABASE LINK TO MONSTER_GAME;
Oracle2のMONSTER_GAMEにログインしてOracle1のMONSTER_GAMEに対してデータベースリンクを設定します。
CREATE DATABASE LINK DBLINK_PLAYER
CONNECT TO MONSTER_GAME IDENTIFIED BY password123
USING '//oracle1:1521/ORCLPDB1';
SELECTしてみるとOracle1から無事データを取得できていることを確認できました。
SQL> COL NAME FORMAT A10
SQL> SELECT * FROM PLAYER@DBLINK_PLAYER;
NAME HP STR DEF
---------- ---------- ---------- ----------
MAGICIAN 10 10 30
THIEF 20 40 30
ASSASSIN 20 60 30
FIGHTER 40 30 30
(Oracle1)マテリアライズド・ビュー・ログを作成
リフレッシュに必要なマテリアライズド・ビュー・ログを作成します。
CREATE MATERIALIZED VIEW LOG ON PLAYER WITH ROWID;
(Oracle2)マテリアライズド・ビューの作成
Oracle2にSYSでログインしてOracle2のMONSTER_GAMEに権限を追加します。
GRANT CREATE MATERIALIZED VIEW TO MONSTER_GAME;
Oracle2のMONSTER_GAMEでマテリアライズド・ビューを作成します。
CREATE MATERIALIZED VIEW PLAYER
AS SELECT * FROM PLAYER@DBLINK_PLAYER;
SELECT文でOracle1のテーブルと同期できていることを確認できました。
SQL> COL NAME FORMAT A10
SQL> SELECT * FROM PLAYER;
NAME HP STR DEF
---------- ---------- ---------- ----------
MAGICIAN 10 10 30
THIEF 20 40 30
ASSASSIN 20 60 30
FIGHTER 40 30 30
(Oracle1)データの追加挿入確認
Oracle1のMONSTER_GAMEでデータ挿入します。
INSERT INTO PLAYER VALUES ('KNIGHT', 80, 30, 20);
INSERT INTO PLAYER VALUES ('BISHOP', 30, 30, 50);
Oracle2のMONSTER_GAMEでリフレッシュします。
EXECUTE DBMS_MVIEW.REFRESH('PLAYER', 'c');
Oracle2のMONSTER_GAMEでSELECT文を実施し、同期できていることを確認できました。
SQL> SELECT * FROM PLAYER;
NAME HP STR DEF
---------- ---------- ---------- ----------
MAGICIAN 10 10 30
THIEF 20 40 30
ASSASSIN 20 60 30
FIGHTER 40 30 30
KNIGHT 80 30 20
BISHOP 30 30 50
6 rows selected.
後片付け
(Oracle2)DBLINK削除
DROP DATABASE LINK DBLINK_PLAYER;
(共通)スキーマと表領域削除
DROP USER MONSTER_GAME CASCADE;
DROP TABLESPACE TABLE_SPACE_MONSTER_GAME INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;
DROP TABLESPACE TEMP_SPACE_MONSTER_GAME INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;
感想
実際に試してみることでどちらのサーバで何をする必要があるかがわかりました。