この章では、レプリケーション・マネージメントAPIを使用した、レプリケーション環境でのレプリケーション・オブジェクトおよびキューの管理方法を説明します。
この章には、次の項が含まれます。
データベースを変更する場合、レプリケート・オブジェクトの特性も変更する必要がある場合があります。DDLを直接実行して、レプリケート・オブジェクトを変更しないでください。直接実行すると、レプリケーション環境に障害が発生する原因となります。
DBMS_REPCAT
パッケージのALTER_MASTER_REPOBJECT
プロシージャを使用して、静止中のマスター・グループにあるレプリケート・オブジェクトの特性を変更します。その場合、次のスクリプト例に示すように、必要なDDLをプロシージャ・コールに含めます(ddl_text
パラメータを参照してください)。
これらのアクションを実行するには、次の要件を満たす必要があります。
実行者: レプリケーション管理者
実行場所: マスター定義サイト
レプリケーションの状態: 静止中
次に示す手順に従って、静止中のマスター・グループにあるレプリケート・オブジェクトを変更します。
注意: このドキュメントをオンラインで参照している場合は、次の「BEGINNING OF SCRIPT」の行から「END OF SCRIPT」の行までのテキストをテキスト・エディタにコピーして編集し、使用している環境に適したスクリプトを作成します。 |
/************************* BEGINNING OF SCRIPT ******************************
更新可能なマテリアライズド・ビューをリフレッシュして、マスター表に変更をプッシュします。手順については、「マテリアライズド・ビューのリフレッシュ」を参照してください。
*/ PAUSE Press <RETURN> to continue when all of the updatable materialized views that are based on the master table have been refreshed. /*
*/
SET ECHO ON SPOOL alter_rep_object.out CONNECT repadmin@orc1.example.com /*
静止が不要な場合の詳細は、「ALTER_MASTER_REPOBJECTプロシージャ」を参照してください。
*/ BEGIN DBMS_REPCAT.SUSPEND_MASTER_ACTIVITY ( gname => 'hr_repg'); END; / /*
グループのステータスがQUIESCED
になるまで進行を中断します。
ステータスをチェックするには、次の問合せを実行します。
SELECT GNAME, STATUS FROM DBA_REPGROUP; */ PAUSE Press <RETURN> to continue when the master group's status is QUIESCED. /*
*/
BEGIN DBMS_REPCAT.ALTER_MASTER_REPOBJECT ( sname => 'hr', oname => 'employees', type => 'TABLE', ddl_text => 'ALTER TABLE hr.employees ADD (timestamp DATE)'); END; / /*
*/
BEGIN DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT ( sname => 'hr', oname => 'employees', type => 'TABLE', min_communication => TRUE); END; / /*
このビューが空になるまで進行を中断します。
他のSQL*Plusセッションで次のSELECT
文を実行して、DBA_REPCATLOG
ビューを監視します。
SELECT * FROM DBA_REPCATLOG WHERE GNAME = 'HR_REPG'; */ PAUSE Press <RETURN> to continue when DBA_REPCATLOG is empty. /*
マスター表に基づく高速リフレッシュが可能なマテリアライズド・ビューがあるマスター表を変更し、かつ、次のいずれかの条件が満たされる場合は、マテリアライズド・ビュー・ログを削除して再作成する必要があります。
マテリアライズド・ビュー・ログには、マスター表に追加された1つ以上の新しい列が含まれている必要がある。この場合には、マテリアライズド・ビュー・ログを変更して、列を追加できます。「列の追加のためのマテリアライズド・ビュー・ログの変更」を参照してください。
マテリアライズド・ビュー・ログには、マスター表の変更された列が1つ以上含まれている。
マテリアライズド・ビュー・ログには、マスター表から削除された列が1つ以上含まれている。
*/ PAUSE Press <RETURN> to continue after the materialized view logs are re-created. /*
マスター表に基づく更新可能なマテリアライズド・ビューがあるマスター表を変更した場合は、これらの更新可能なマテリアライズド・ビューをすべて再作成する必要があります。
マスター表に基づく読取り専用のマテリアライズド・ビューがあるマスター表を変更し、かつ、次のいずれかの条件が満たされる場合は、これらの読取り専用のマテリアライズド・ビューを再作成する必要があります。
読取り専用のマテリアライズド・ビューは、マスター表に追加された1つ以上の列を参照する必要がある。
読取り専用のマテリアライズド・ビューは、マスター表の変更された列を1つ以上参照する。
読取り専用のマテリアライズド・ビューは、マスター表から削除された列を1つ以上参照する。
*/ PAUSE Press <RETURN> to continue after the materialized views are re-created. /*
*/
BEGIN DBMS_REPCAT.RESUME_MASTER_ACTIVITY ( gname => 'hr_repg'); END; / SET ECHO OFF SPOOL OFF /************************* END OF SCRIPT **********************************/
レプリケート・オブジェクトを変更する必要があるが、この変更をレプリケーション環境の他のサイトにレプリケートしない場合があります。たとえば、次の状況でレプリケーションを使用禁止にする必要があります。
プロシージャ・レプリケーションを使用して変更を伝播するときは、必ずプロシージャの開始時に行レベル・レプリケーションを使用禁止にします。
トリガー・アクションを複数回レプリケートするのを回避するため、レプリケート表で定義されたトリガー中のレプリケーションを使用禁止にする必要がある場合があります。詳細は、「レプリケート・トリガーの起動を1回のみにする」を参照してください。
競合を手動で解決する場合、表の他のコピーにこの変更をレプリケートしない場合があります。
これが必要になるのは、たとえば、エラー・トランザクションを再実行したときに競合するレプリケート更新が成功するように、1つのサイトのレコードの状態を訂正する必要がある場合です。または、トランザクションが接続先サイトで適用できなかったため、起点サイトでのトランザクションの効果を取り消すために、レプリケートされない変更を使用する場合があります。この例では、Oracle Enterprise ManagerのAdvanced Replicationインタフェースを使用して、競合するトランザクションを接続先サイトから削除できます。
変更をレプリケートせずに表を変更するには、DBMS_REPUTIL
パッケージのREPLICATION_ON
プロシージャおよびREPLICATION_OFF
プロシージャを使用します。これらのプロシージャは引数を取らず、生成されたレプリケーション・トリガーでフラグとして使用されます。
注意: レプリケーションを使用可能または使用禁止にするには、DBMS_REPUTIL パッケージのEXECUTE 権限を持っている必要があります。 |
DBMS_REPUTIL.REPLICATION_OFF
プロシージャは、カレント・セッションに関する内部レプリケーション変数の状態をFALSE
に設定します。すべてのレプリケート・トリガーが、トランザクションをキューに入れる前にこの変数の状態をチェックするため、行レベル・レプリケーションを使用してレプリケート表を変更しても、遅延トランザクションはキューに入れられません。
注意: レプリケーションのオンまたはオフの切り替えは、カレント・セッションにのみ適用されます。すなわち、現在同じサーバーに接続している他のユーザーは、遅延トランザクション・キューでコミットされる変更の入力を制限されません。 |
プロシージャ・レプリケーションを使用している場合は、次の例に示すようにプロシージャの開始時にREPLICATION_OFF
をコールします。これにより、レプリケーション機能により行レベル・レプリケーションが使用されて変更が伝播されることがなくなります。
CREATE OR REPLACE PACKAGE update_objects AS PROCEDURE update_emp(adjustment IN NUMBER); END; / CREATE OR REPLACE PACKAGE BODY update_objects AS PROCEDURE update_emp(adjustment IN NUMBER) IS BEGIN --turn off row-level replication for set update DBMS_REPUTIL.REPLICATION_OFF; UPDATE emp . . .; --reenable replication DBMS_REPUTIL.REPLICATION_ON; EXCEPTION WHEN OTHERS THEN . . . DBMS_REPUTIL.REPLICATION_ON; END; END; /
競合を解消した後、またはレプリケート・プロシージャの終了時に、必ずDBMS_REPUTIL.REPLICATION_ON
をコールし、レプリケート表またはマテリアライズド・ビューに対する変更の通常のレプリケーションを再開してください。このプロシージャは引数を取りません。REPLICATION_ON
のコールにより、内部レプリケーション変数がTRUE
に設定されます。
レプリケート表でレプリケート・トリガーを定義済の場合、変更を行うごとにトリガーが1回のみ起動するようにする必要がある場合があります。通常は、トリガーを起動するのは変更が最初に行われたときのみで、変更がリモート・サイトにレプリケートされたときはリモート・トリガーを起動しません。
トリガーの開始時にDBMS_REPUTIL.FROM_REMOTE
パッケージ変数の値をチェックする必要があります。この変数の値がFALSE
の場合のみ、トリガーで表が更新される必要があります。
または、トリガーを起動する行以外の行を変更する場合は、トリガーの開始時にレプリケーションを使用禁止にし、トリガーの終了時に再び使用可能にできます。この方法により、元の変更のみがリモート・サイトにレプリケートされます。これによりレプリケート・トリガーが各リモート・サイトで起動します。レプリケート・トリガーで実行される更新は、他のサイトにプッシュされません。
このアプローチでは、競合解消はコールされません。このため、トリガーにより生じる変更がデータの整合性に影響しないようにする必要があります。
BASICFILE
記憶域を使用するLOB列はレプリケートできますが、LONG
列はレプリケートできません。LONG
列からCLOB
列へのデータ型の変換、およびLONG_RAW
列からBLOB
列へのデータ型の変換が可能です。
LONG
列をLOB列に変換すると、このような列のデータは変換後にレプリケートされるため、ネットワーク帯域幅の要件が増加する可能性があります。この項のプロシージャを実行する前に、十分なネットワーク帯域幅があることを確認してください。
注意: SECUREFILE 記憶域を使用するLOB列は、レプリケートできません。 |
関連項目: アプリケーションの詳細およびLONG からLOBへの変換の詳細は、『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』を参照してください。 |
次に示す手順に従って、レプリケート表でLONG
列をLOB列に変換します。
LONG
列を含む表がマスター表として構成されている場合は、LONG
列のデータへの変更はレプリケートされません。このため、LONG
列のデータがすべてのレプリケーション・サイトで一致しない場合があります。変換前に、LONG
列のデータがすべてのマスター・サイトで一致することを確認する必要があります。
CONNECT repadmin@orc1.example.com
BEGIN
DBMS_REPCAT.SUSPEND_MASTER_ACTIVITY ( gname => 'sales_mg'); END; /
BEGIN
DBMS_REPCAT.ALTER_MASTER_REPOBJECT ( sname => 'staff', oname => 'positions', type => 'TABLE', ddl_text => 'ALTER TABLE staff.positions MODIFY (job_desc CLOB)'); END; /
類似したALTER
TABLE
文を使用して、LONG_RAW
列をBLOB
列に変換できます。
BEGIN
DBMS_REPCAT.GENERATE_REPLICATION_SUPPORT ( sname => 'staff', oname => 'positions', type => 'TABLE', min_communication => TRUE); END; /
BEGIN
DBMS_REPCAT.RESUME_MASTER_ACTIVITY ( gname => 'sales_mg'); END; /
必要な場合は、マテリアライズド・ビューを再作成します。
レプリケート表間に違いが生じる場合があります。レプリケーション環境を管理するとき、2つのレプリケート表の内容が同じであるかどうかを定期的にチェックできます。DBMS_RECTIFIER_DIFF
パッケージ内の次のプロシージャを使用すると、2つの表の違いを識別でき、また任意で調整もできます。
注意: DBMS_COMPARISON パッケージを使用して、データベース・オブジェクト間の相違点を特定し、収束することもできます。 |
関連項目:
|
DIFFERENCES
プロシージャは、1つの表の2つのレプリカを比較し、第1のレプリカにあるが第2のレプリカにはない行、および第2のレプリカにあるが第1のレプリカにはない行をすべて判別します。このプロシージャの出力は、ユーザーが作成した2つの表に格納されます。第1の表には欠落行の値が格納され、第2の表にはそれぞれの欠落行を含むサイトを示す情報が格納されます。
RECTIFY
プロシージャは、DIFFERENCES
プロシージャで生成された情報を使用して、2つの表を調整します。第1の表にはあるが第2の表にはない行はすべて、第2の表に挿入されます。第2の表にはあるが第1の表にはない行はすべて、第2の表から削除されます。
レプリケート表のコピーをすべて同一にリストアするには、次の手順に従います。
他のすべての表のレプリカを必要に応じて更新するときに、このコピーを使用します。
たとえば、前回の違いのチェック以降に更新されていない行は、チェックしなくてもよい場合があります。すべての列をチェックする必要はありませんが、列のリストには、表の主キーを構成する(または代替識別キーとして指定した)列がすべて含まれている必要があります。
まず、比較する列のデータを保持する表を作成する必要があります。たとえば、employees
表のemployee_id
列、salary
列およびdepartment_id
列を比較する場合は、次のようなCREATE
文を実行する必要があります。
CREATE TABLE hr.missing_rows_data ( employee_id NUMBER(6), salary NUMBER(8,2), department_id NUMBER(4));
次に、行が検出された位置を示す表も作成する必要があります。この表には、次の例に示すデータ型の列を3つ入れる必要があります。
CREATE TABLE hr.missing_rows_location ( present VARCHAR2(128), absent VARCHAR2(128), r_id ROWID);
グループのレプリケーション・アクティビティの中断は必須ではありませんが、最初に表を静止せずに調整すると、データに不整合が生じることがあります。
CONNECT repadmin BEGIN DBMS_REPCAT.SUSPEND_MASTER_ACTIVITY ( gname => 'hr_repg'); END; /
たとえば、ニューヨークのサイトとサンフランシスコのサイトのemployees
表を比較する場合、次のようなプロシージャをコールします。
BEGIN DBMS_RECTIFIER_DIFF.DIFFERENCES ( sname1 => 'hr', oname1 => 'employees', reference_site => 'ny.example.com', sname2 => 'hr', oname2 => 'employees', comparison_site => 'mv4.example.com', where_clause => '', column_list => 'employee_id,salary,department_id', missing_rows_sname => 'hr', missing_rows_oname1 => 'missing_rows_data', missing_rows_oname2 => 'missing_rows_location', missing_rows_site => 'ny.example.com', max_missing => 500, commit_rows => 50); END; /
図9-1に、employee
表の2つのレプリカと、これらのレプリカに対してDIFFERENCES
プロシージャを実行した場合に出力される欠落行表の例を示します。
2つの欠落行表が、ROWID
およびr_id
列によって対応付けられている点に注目してください。
BEGIN
DBMS_RECTIFIER_DIFF.RECTIFY ( sname1 => 'hr', oname1 => 'employees', reference_site => 'ny.example.com', sname2 => 'hr', oname2 => 'employees', comparison_site => 'mv4.example.com', column_list => 'employee_id,salary,department_id', missing_rows_sname => 'hr', missing_rows_oname1 => 'missing_rows_data', missing_rows_oname2 => 'missing_rows_location', missing_rows_site => 'ny.example.com', commit_rows => 50); END; /
必要な挿入および削除を実行している間、その変更を伝播しないよう、RECTIFY
プロシージャは、比較サイトのレプリケーションを一時的に使用禁止にします。RECTIFY
は、最初に必要なDELETE
操作をすべて実行し、次にINSERT
操作をすべて実行します。これによって、主
キー
制約の違反は発生しなくなります。
RECTIFY
プロシージャが正常に実行されると、欠落行表は空になります。
注意: 比較表にその他の制約がある場合は、RECTIFY のコール時にそれらに違反しないようにする必要があります。欠落行表の情報を使用して、表を直接更新することが必要な場合もあります。その場合は、必ず欠落行表から該当の行をDELETE してください。 |
このプロシージャの完了時にすべてのコピーが確実に同一になるように、必ず毎回同じ参照表を使用してください。
BEGIN DBMS_REPCAT.RESUME_MASTER_ACTIVITY ( gname => 'hr_repg'); END; /
通常、Advanced Replicationは、遅延トランザクション・キューのプッシュおよびパージを自動的に行うように構成されます。ただし、遅延トランザクション・キューのプッシュやパージを手動で行う必要があることもあります。遅延トランザクション・キューをプッシュするプロセスは、マスター・サイトでもマテリアライズド・ビュー・サイトでも同じです。
マスター・サイトは、遅延トランザクション・キューのプッシュを設定された間隔で自動的に行うように構成されます。マテリアライズド・ビュー・サイトでは、マテリアライズド・ビューのリフレッシュ時に、遅延トランザクション・キューのトランザクションを自動的に伝播させない場合は、次の手順を実行して、更新可能なマテリアライズド・ビューに加えられた変更をそのマスター表またはマスター・マテリアライズド・ビューに伝播します。
この例では、マテリアライズド・ビュー・サイトでの遅延トランザクション・キューのプッシュを示しますが、そのプロセスはマスター・サイトでもマテリアライズド・ビュー・サイトでも同じです。
実行者: マテリアライズド・ビュー管理者
実行場所: マテリアライズド・ビュー・サイト
次の手順に従います。
CONNECT mviewadmin@mv1.example.com
遅延トランザクション・キューの伝播は、トランザクションの接続先をベースにします。それぞれ固有の接続先と、その接続先に保留されているトランザクションの数が表示されます。
SELECT DISTINCT(dblink), COUNT(deferred_tran_id) FROM deftrandest GROUP BY dblink;
DECLARE temp INTEGER; BEGIN temp := DBMS_DEFER_SYS.PUSH ( destination => 'orc1.example.com', stop_on_error => FALSE, delay_seconds => 0, parallelism => 0); END; /
手順2で実行したSELECT
文で戻された各接続先に、PUSH
プロシージャを実行します。
遅延トランザクション・キュー内の正常に伝播されたトランザクションを、定期的に自動的にパージするようにシステムが設定されていない場合は、次の手順を実行して、手動でパージする必要があります。
この例では、マテリアライズド・ビュー・サイトでの遅延トランザクション・キューのパージを示しますが、そのプロセスはマスター・サイトでもマテリアライズド・ビュー・サイトでも同じです。
実行者: マテリアライズド・ビュー管理者
実行場所: マテリアライズド・ビュー・サイト
次の手順に従います。
CONNECT mviewadmin@mv1.example.com
DECLARE
temp INTEGER; BEGIN temp := DBMS_DEFER_SYS.PURGE ( purge_method => DBMS_DEFER_SYS.PURGE_METHOD_QUICK); END; /
注意: purge_method_quick パラメータを使用する場合は、正常にプッシュされた遅延トランザクションおよび遅延プロシージャ・コールが、パージされるまで、それぞれDEFTRAN およびDEFCALL データ・ディクショナリ・ビューに予想以上に長時間保持されることがあります。詳細は、DBMS_DEFER_SYS.PURGE に関する「使用上の注意」を参照してください。 |
レプリケート表で列オブジェクト、コレクションまたはREF
を使用している場合、DBMS_DEFER_QUERY
パッケージのGET_ANYDATA_ARG
ファンクションを使用して、これらのユーザー定義型の1つを含む遅延コールの引数の値を判定できます。
次の例は、GET_ANYDATA_ARG
ファンクションの使用方法を示します。この例では、oe
サンプル・スキーマで次のユーザー定義型を使用します。
CREATE TYPE phone_list_typ AS VARRAY(5) OF VARCHAR2(25); / CREATE TYPE warehouse_typ AS OBJECT (warehouse_id NUMBER(3), warehouse_name VARCHAR2(35), location_id NUMBER(4) ); / CREATE TYPE inventory_typ AS OBJECT (product_id NUMBER(6), warehouse warehouse_typ, quantity_on_hand NUMBER(8) ); / CREATE TYPE inventory_list_typ AS TABLE OF inventory_typ; /
次のプロシージャは、遅延トランザクション・キューに格納されたコールのコレクション、オブジェクトおよびREF
インスタンスの引数値を取得します。このプロシージャは、コール番号およびトランザクションIDが使用可能であることを前提としています。
プロシージャを作成するユーザーは、DBMS_DEFER_QUERY
パッケージのEXECUTE
権限を持っていることと、CREATE
PROCEDURE
権限を持っていることが必要です。この例では、oe
サンプル・スキーマを使用します。このため、この例を実行するには、oe
ユーザーにこれらの権限を与える必要があります。管理ユーザーとして接続して、次のように入力します。
GRANT EXECUTE ON DBMS_DEFER_QUERY TO oe; GRANT CREATE PROCEDURE TO oe; CONNECT oe@orc1.example.com CREATE OR REPLACE PROCEDURE get_userdef_arg AS call_no NUMBER := 0; txn_id VARCHAR2(128) := 'xx.xx.xx'; anydata_val ANYDATA; t ANYTYPE; data_pl phone_list_typ; -- varray data_ntt inventory_list_typ; -- nested table type data_p warehouse_typ; -- object type ref1 REF inventory_typ; -- REF type rval PLS_INTEGER; -- return value tc PLS_INTEGER; -- return value prec PLS_INTEGER; -- precision scale PLS_INTEGER; -- scale len PLS_INTEGER; -- length csid PLS_INTEGER; -- character set id csfrm PLS_INTEGER; -- character set form cnt PLS_INTEGER; -- count of varray elements or number of -- object attributes sname VARCHAR2(35); -- schema name type_name VARCHAR2(35); -- type name version VARCHAR2(35); BEGIN FOR i IN 1 .. 5 LOOP anydata_val := DBMS_DEFER_QUERY.GET_ANYDATA_ARG(call_no, i, txn_id); -- Get the type information, including type name. tc := anydata_val.GetType(t); tc := t.GetInfo(prec, scale, len, csid, csfrm, sname, type_name, version, cnt); -- Based on the type name, convert the anydata value to the appropriate -- user-defined types. IF type_name = 'PHONE_LIST_TYP' THEN -- The anydata_val contains phone_list_typ varray instance. rval := anydata_val.GetCollection(data_pl); -- Do something with data_pl. ELSIF type_name = 'INVENTORY_LIST_TYP' THEN -- anydata_val contains inventory_list_typ nested table instance. rval := anydata_val.GetCollection(data_ntt); -- Do something with data_ntt. ELSIF type_name = 'WAREHOUSE_TYP' THEN -- The anydata_val contains warehouse_typ object instance. rval := anydata_val.GetObject(data_p); -- Do something with data_p. ELSIF type_name = 'INVENTORY_TYP' THEN -- The anydata_val contains a reference to inventory_typ object instance. rval := anydata_val.GetRef(ref1); -- Do something with ref1. END IF; END LOOP; END; /
関連項目:
|
レプリケーション環境の管理者は、エラー・キューを定期的に監視し、ターゲット・マスター・サイトに正常に適用されなかった遅延トランザクションがあるかどうかを確認します。
エラー・キューを調べるには、ターゲット・マスター・サイトに接続した状態で、次のSELECT
文を(レプリケーション管理者として)実行します。
SELECT * FROM deferror;
エラー・キューにエラーがあった場合は、エラー条件を解決し、遅延トランザクションを再実行します。遅延トランザクションを再実行するには、遅延トランザクションを受信したユーザーのセキュリティ・コンテキストで再実行するか、または別のセキュリティ・コンテキストで再実行するという、2通りの方法があります。
注意: エラー・トランザクションが複数ある場合に、確実に正しい順序で再実行するには、次の項のプロシージャでdeferred_tran_id パラメータにNULL を指定できます。NULL を指定しない場合、個々のトランザクションが不正な順序で再実行され、競合の原因となる場合があります。 |
次に示すプロシージャは、遅延トランザクションを受信したユーザーのセキュリティ・コンテキストで、指定された遅延トランザクションを再実行します。このプロシージャは、エラー条件が解決した後で実行します。
これらのアクションを実行するには、次の要件を満たす必要があります。
実行者: レプリケーション管理者
実行場所: エラーの発生したサイト
レプリケーションの状態: 通常
次の手順に従います。
SQL*Plusでデータベースに接続する方法については、『Oracle Database管理者ガイド』を参照してください。
BEGIN
DBMS_DEFER_SYS.EXECUTE_ERROR ( deferred_tran_id => '1.12.2904', destination => 'orc2.example.com'); END; /
次に示すプロシージャは、カレント接続ユーザーのセキュリティ・コンテキストで、指定された遅延トランザクションを再実行します。このプロシージャは、エラー条件が解決した後で実行します。
これらのアクションを実行するには、次の要件を満たす必要があります。
実行者: 接続ユーザー
実行場所: エラーの発生したサイト
レプリケーションの状態: 通常
次の手順に従います。
SQL*Plusでデータベースに接続する方法については、『Oracle Database管理者ガイド』を参照してください。
BEGIN
DBMS_DEFER_SYS.EXECUTE_ERROR_AS_USER ( deferred_tran_id => '1.12.2904', destination => 'orc2.example.com'); END; /