適用プロセスは、Oracle Streams環境で暗黙的に情報をコンシュームします。論理変更レコード(LCR)およびユーザー・メッセージを特定のキューからデキューして、各メッセージを直接適用するか、パラメータとしてユーザー定義プロシージャに渡します。
次の各項では、Oracle Streamsの適用プロセスの管理について説明します。
この章で説明する各タスクは、特に明記されていないかぎり、適切な権限を付与されているOracle Streams管理者が完了する必要があります。
既存の適用プロセスを起動するには、DBMS_APPLY_ADMパッケージのSTART_APPLYプロシージャを実行します。たとえば、次のプロシージャでは適用プロセスstrm01_applyが起動されます。
BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name => 'strm01_apply');
END;
/
|
関連項目: Oracle Enterprise Managerを使用した適用プロセスの起動については、Oracle Database 2日でデータ・レプリケーションおよび統合ガイドを参照 |
既存の適用プロセスを停止するには、DBMS_APPLY_ADMパッケージのSTOP_APPLYプロシージャを実行します。たとえば、次のプロシージャでは適用プロセスstrm01_applyが停止されます。
BEGIN
DBMS_APPLY_ADM.STOP_APPLY(
apply_name => 'strm01_apply');
END;
/
|
関連項目: Oracle Enterprise Managerでの適用プロセスの停止方法については、Oracle Database 2日でデータ・レプリケーションおよび統合ガイドを参照 |
この項では、次のタスクの実行手順を説明します。
適用プロセスには、1つのポジティブ・ルール・セットおよび1つのネガティブ・ルール・セットを指定できます。適用プロセスでは、メッセージは、ポジティブ・ルール・セットの少なくとも1つのルールについてTRUEと評価される場合は適用され、ネガティブ・ルール・セットの少なくとも1つのルールについてTRUEと評価される場合は廃棄されます。ネガティブ・ルール・セットは、ポジティブ・ルール・セットの前に評価されます。
既存のルール・セットをポジティブ・ルール・セットとして既存の適用プロセスに指定するには、ALTER_APPLYプロシージャのrule_set_nameパラメータを使用します。このプロシージャは、DBMS_APPLY_ADMパッケージに含まれています。
たとえば、次のプロシージャでは、適用プロセスstrm01_applyのポジティブ・ルール・セットがstrm02_rule_setに設定されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm01_apply',
rule_set_name => 'strmadmin.strm02_rule_set');
END;
/
既存のルールセットをネガティブ・ルール・セットとして既存の適用プロセスに指定するには、ALTER_APPLYプロシージャのnegative_rule_set_nameパラメータを使用します。このプロシージャは、DBMS_APPLY_ADMパッケージに含まれています。
たとえば、次のプロシージャでは、適用プロセスstrm01_applyのネガティブ・ルール・セットがstrm03_rule_setに設定されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm01_apply',
negative_rule_set_name => 'strmadmin.strm03_rule_set');
END;
/
適用プロセスのルール・セットにルールを追加するには、次のプロシージャのいずれかを実行します。
DBMS_STREAMS_ADM.ADD_TABLE_RULES
DBMS_STREAMS_ADM.ADD_SUBSET_RULES
DBMS_STREAMS_ADM.ADD_SCHEMA_RULES
DBMS_STREAMS_ADM.ADD_GLOBAL_RULES
ADD_SUBSET_RULESプロシージャ以外のこれらのプロシージャでは、適用プロセスのポジティブ・ルール・セットまたはネガティブ・ルール・セットにルールを追加できます。ADD_SUBSET_RULESプロシージャでは、適用プロセスのポジティブ・ルール・セットにのみルールを追加できます。
次の例では、DBMS_STREAMS_ADMパッケージのADD_TABLE_RULESプロシージャを実行して、適用プロセスstrm01_applyのポジティブ・ルール・セットにルールを追加します。
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'hr.departments',
streams_type => 'apply',
streams_name => 'strm01_apply',
queue_name => 'streams_queue',
include_dml => TRUE,
include_ddl => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule => TRUE);
END;
/
このプロシージャを実行すると、次のアクションが実行されます。
ルールが1つ作成されます。このルールは、hr.departments表に対するDML変更の結果を含む行LCRについてTRUEと評価されます。ルール名はシステムによって生成されます。
ルールが1つ作成されます。このルールは、hr.departments表に対するDDL変更を含むDDL LCRについてTRUEと評価されます。ルール名はシステムによって生成されます。
どちらのルールも、dbs1.example.comソース・データベースで変更が発生したLCRに対してのみTRUEと評価されるように指定されます。
inclusion_ruleパラメータがTRUEに設定されているため、そのルールは適用プロセスに関連付けられたポジティブ・ルール・セットに追加されます。
次の例では、DBMS_STREAMS_ADMパッケージのADD_TABLE_RULESプロシージャを実行して、適用プロセスstrm01_applyのネガティブ・ルール・セットにルールを追加します。
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'hr.regions',
streams_type => 'apply',
streams_name => 'strm01_apply',
queue_name => 'streams_queue',
include_dml => TRUE,
include_ddl => TRUE,
source_database => 'dbs1.example.com',
inclusion_rule => FALSE);
END;
/
このプロシージャを実行すると、次のアクションが実行されます。
ルールが1つ作成されます。このルールは、hr.regions表に対するDML変更の結果を含む行LCRについてTRUEと評価されます。ルール名はシステムによって生成されます。
ルールが1つ作成されます。このルールは、hr.regions表に対するDDL変更を含むDDL LCRについてTRUEと評価されます。ルール名はシステムによって生成されます。
どちらのルールも、dbs1.example.comソース・データベース で変更が発生したLCRに対してのみ TRUEと評価されるように指定されます。
inclusion_ruleパラメータがFALSEに設定されているため、そのルールは適用プロセスに関連付けられたネガティブ・ルール・セットに追加されます。
既存の適用プロセスのルール・セットからルールを削除するには、DBMS_STREAMS_ADMパッケージのREMOVE_RULEプロシージャを実行します。たとえば、次のプロシージャでは、適用プロセスstrm01_applyのポジティブ・ルール・セットからルールdepartments3が削除されます。
BEGIN
DBMS_STREAMS_ADM.REMOVE_RULE(
rule_name => 'departments3',
streams_type => 'apply',
streams_name => 'strm01_apply',
drop_unused_rule => TRUE,
inclusion_rule => TRUE);
END;
/
この例では、REMOVE_RULEプロシージャのdrop_unused_ruleパラメータがTRUEに設定されています。これはデフォルトの設定です。したがって、削除するルールが他のどのルール・セットにも含まれていなければ、そのルールはデータベースから削除されます。drop_unused_ruleパラメータがFALSEに設定されている場合、ルールはルール・セットから削除されますが、他のどのルール・セットにも含まれていない場合でも、データベースからは削除されません。
inclusion_ruleパラメータをFALSEに設定すると、REMOVE_RULEプロシージャによって、適用プロセスのポジティブ・ルール・セットからではなく、ネガティブ・ルール・セットからルールが削除されます。
適用プロセスのルール・セットからすべてのルールを削除するには、REMOVE_RULEプロシージャの実行時にrule_nameパラメータにNULLを指定します。
既存の適用プロセスから ルール・セットを削除するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャを使用します。このプロシージャでは、ポジティブ・ルール・セットまたはネガティブ・ルール・セット、あるいはその両方を削除できます。適用プロセスのポジティブ・ルール・セットを削除するには、remove_rule_setパラメータにTRUEを設定します。適用プロセスのネガティブ・ルール・セットを削除するには、remove_negative_rule_setパラメータにTRUEを設定します。
たとえば、次のプロシージャでは、適用プロセスstrm01_applyからポジティブ・ルール・セットとネガティブルール・セットの両方が削除されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm01_apply',
remove_rule_set => TRUE,
remove_negative_rule_set => TRUE);
END;
/
適用プロセス・パラメータを設定するには、DBMS_APPLY_ADMパッケージのSET_PARAMETERプロシージャを使用します。適用プロセス・パラメータでは、適用プロセスの動作を制御します。
たとえば、次のプロシージャでは、適用プロセスstrm01_applyのcommit_serializationパラメータがNONEに設定されます。commit_serializationパラメータをこの値に設定にすると、適用プロセスはトランザクションを任意の順序でコミットできます。
BEGIN
DBMS_APPLY_ADM.SET_PARAMETER(
apply_name => 'strm01_apply',
parameter => 'commit_serialization',
value => 'none');
END;
/
|
注意:
|
|
関連項目:
|
適用ユーザーは、適用プロセスのルール・セットを満たすすべてのDML変更およびDDL変更を適用し、ユーザー定義の適用ハンドラを実行するユーザーです。適用プロセスの適用ユーザーを設定するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャでapply_userパラメータを使用します。
適用ユーザーを変更するには、ALTER_APPLYプロシージャを起動するユーザーにDBAロールが付与されている必要があります。SYSユーザーのみが、SYSにapply_userを設定できます。
たとえば、次のプロシージャでは、適用プロセスstrm03_applyの適用ユーザーがhrに設定されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm03_apply',
apply_user => 'hr');
END;
/
このプロシージャを実行すると、新しい適用ユーザーに、適用プロセスで使用されるキューのデキュー権限が付与され、そのユーザーがキューの保護キュー・ユーザーとして構成されます。また、適用ユーザーが次の権限を持っていることを確認する必要があります。
適用プロセスで使用するルール・セットのEXECUTE権限
ルール・セットで使用するすべてのカスタム・ルールベースの変換ファンクションのEXECUTE権限
すべての適用ハンドラ・プロシージャのEXECUTE権限
これらの権限は、適用ユーザーに直接付与する必要があります。これらは、ロールを介して付与できません。
|
注意: Oracle Database Vaultがインストールされている場合は、適用ユーザーを変更するユーザーにBECOME USERシステム権限を付与する必要があります。Oracle Database Vaultがインストールされていない場合は、ユーザーにこの権限を付与する必要はありません。適用ユーザーを変更した後は、必要に応じて、そのユーザーからBECOME USERシステム権限を取り消すことができます。 |
メッセージ・ハンドラは、永続ユーザー・メッセージを処理する適用ハンドラです。次の各項では、適用プロセスにメッセージ・ハンドラを設定または設定解除する手順について説明します。
|
関連項目:
|
適用プロセスのメッセージ・ハンドラを設定するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャでmessage_handlerパラメータを使用します。たとえば、次のプロシージャでは、適用プロセスstrm03_applyのメッセージ・ハンドラがoeスキーマ内のmes_handlerプロシージャに設定されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm03_apply',
message_handler => 'oe.mes_handler');
END;
/
ALTER_APPLYプロシージャを実行するユーザーは、指定したメッセージ・ハンドラのEXECUTE権限を持っている必要があります。メッセージ・ハンドラが適用プロセスにすでに設定されている場合は、ALTER_APPLYプロシージャを実行して、適用プロセスのメッセージ・ハンドラを変更できます。
適用プロセスのメッセージ・ハンドラを設定解除するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャでremove_message_handlerパラメータをTRUEに設定します。たとえば、次のプロシージャでは、適用プロセスstrm03_applyのメッセージ・ハンドラの設定が解除されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm03_apply',
remove_message_handler => TRUE);
END;
/
プリコミット・ハンドラは、トランザクションのコミット情報を受信し、カスタマイズした方法でコミット情報を処理できる適用ハンドラです。
次の各項では、適用プロセスのプリコミット・ハンドラの作成、設定および設定解除の手順について説明します。
プリコミット・ハンドラには、次のシグネチャが必要です。
PROCEDURE handler_procedure ( parameter_name IN NUMBER);
handler_procedureはプロシージャ名で、parameter_nameはプロシージャに渡されるパラメータの名前です。プロシージャに渡されるパラメータは、適用プロセスで使用されるキューに含まれる内部コミット・ディレクティブのコミットSCNです。
プリコミット・ハンドラを使用すると、適用プロセスによって処理されたコミットの情報を記録できます。適用プロセスでは、取得LCR、永続LCRまたは永続ユーザー・メッセージを適用できます。取得された行LCRの場合は、コミット・ディレクティブに、ソース・データベースからのトランザクションのコミットSCNが含まれます。永続LCRおよび永続ユーザー・メッセージの場合、コミットSCNは適用プロセスによって生成されます。
プリコミット・ハンドラ・プロシージャは、次の制限に従う必要があります。
コミットする作業は、自律型トランザクションである必要があります。
プロシージャで作成された指定のセーブ・ポイントまでロールバックする必要があります。
プリコミット・ハンドラで例外が発生した場合、適用トランザクション全体がロールバックされ、トランザクション内のすべてのメッセージがエラー・キューに移動されます。
たとえば、プリコミット・ハンドラは、適用プロセスによって適用された行LCRの監査に使用できます。このようなプリコミット・ハンドラを1つ以上の個別のDMLハンドラとともに使用し、トランザクションのソース・データベースのコミットSCNを監査表に記録します。また、適用プロセスがトランザクションを適用する時間を監査表に記録する場合もあります。
特に、この例では、次の表の行LCRの情報を記録するDMLハンドラとともに使用されるプリコミット・ハンドラが作成されます。
CREATE TABLE strmadmin.history_row_lcrs(
timestamp DATE,
source_database_name VARCHAR2(128),
command_type VARCHAR2(30),
object_owner VARCHAR2(32),
object_name VARCHAR2(32),
tag RAW(10),
transaction_id VARCHAR2(10),
scn NUMBER,
commit_scn NUMBER,
old_values SYS.LCR$_ROW_LIST,
new_values SYS.LCR$_ROW_LIST)
NESTED TABLE old_values STORE AS old_values_ntab
NESTED TABLE new_values STORE AS new_values_ntab;
DMLハンドラは、適用プロセスによって処理される行LCRごとに、strmadmin.history_row_lcrs表に1行挿入します。この例で作成されるプリコミット・ハンドラは、トランザクションのコミット時に、strmadmin.history_row_lcrs表に1行挿入します。
history_row_lcrs表にコミット情報を挿入するプロシージャを作成します。
CREATE OR REPLACE PROCEDURE strmadmin.history_commit(commit_number IN NUMBER)
IS
BEGIN
-- Insert commit information into the history_row_lcrs table
INSERT INTO strmadmin.history_row_lcrs (timestamp, commit_scn)
VALUES (SYSDATE, commit_number);
END;
/
プリコミット・ハンドラは、適用プロセスによってデキューされたすべてのコミット・ディレクティブを処理します。適用プロセスにプリコミット・ハンドラを設定すると、適用プロセスがデキューするすべてのコミット・ディレクティブの処理に使用されます。適用プロセスには1つのプリコミット・ハンドラのみを設定できます。
適用プロセスのプリコミット・ハンドラを設定するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャでprecommit_handlerパラメータを使用します。たとえば、次のプロシージャでは、適用プロセスstrm01_applyのプリコミット・ハンドラにstrmadminスキーマのhistory_commitプロシージャが設定されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm01_apply',
precommit_handler => 'strmadmin.history_commit');
END;
/
また、DBMS_APPLY_ADMパッケージのCREATE_APPLYプロシージャを使用して適用プロセスを作成する際に、プリコミット・ハンドラを指定することもできます。適用プロセスにプリコミット・ハンドラがすでに設定されている場合は、ALTER_APPLYプロシージャを実行して、適用プロセスのプリコミット・ハンドラを変更できます。
適用プロセスのプリコミット・ハンドラを設定解除するには、DBMS_APPLY_ADMパッケージのALTER_APPLYプロシージャでremove_precommit_handlerパラメータをTRUEに設定します。たとえば、次のプロシージャでは、適用プロセスstrm01_applyのプリコミット・ハンドラの設定が解除されます。
BEGIN
DBMS_APPLY_ADM.ALTER_APPLY(
apply_name => 'strm01_apply',
remove_precommit_handler => TRUE);
END;
/
この項では、ポジティブ・ルール・セットに指定したルールを使用する適用プロセスで、ルールを満たすメッセージがエンキューされる宛先キューを設定する手順について説明します。また、宛先キューの設定を削除する手順についても説明します。
特定のルールを満たすメッセージの宛先キューを設定するには、DBMS_APPLY_ADMパッケージのSET_ENQUEUE_DESTINATIONプロシージャを使用します。たとえば、ルールemployees5の宛先キューをキューhr.change_queueに設定するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.SET_ENQUEUE_DESTINATION(
rule_name => 'employees5',
destination_queue_name => 'hr.change_queue');
END;
/
このプロシージャでは、ルールのアクション・コンテキストを変更してキューを指定します。ポジティブ・ルール・セットにemployees5ルールが含まれるローカル・データベースのすべての適用プロセスで、employees5ルールを満たすメッセージがhr.change_queueにエンキューされます。employees5ルールの宛先キューを変更する場合は、SET_ENQUEUE_DESTINATIONプロシージャを再実行して異なるキューを指定します。
指定したルールを使用する各適用プロセスの適用ユーザーは、指定したキューにメッセージをエンキューするために必要な権限を持っている必要があります。キューが保護キューの場合、適用ユーザーはキューの保護キュー・ユーザーである必要があります。
SET_ENQUEUE_DESTINATIONプロシージャを使用してエンキューされたメッセージは、手動でエンキューされている他のすべてのメッセージと同様です。このメッセージに対して、手動でのデキュー、apply_capturedパラメータをFALSEに設定して作成された適用プロセスによる適用、または他のキューへの伝播を実行できます。
|
注意:
|
指定したルールを満たすメッセージの宛先キューを削除するには、DBMS_APPLY_ADMパッケージのSET_ENQUEUE_DESTINATIONプロシージャを使用します。具体的には、このプロシージャで、ルールのdestination_queue_nameパラメータをNULLに設定します。ルールの宛先キューの指定が削除された場合、ルールを満たすメッセージは、適用プロセスによってキューにエンキューされません。
たとえば、ルールemployees5の宛先キューを削除するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.SET_ENQUEUE_DESTINATION(
rule_name => 'employees5',
destination_queue_name => NULL);
END;
/
ポジティブ・ルール・セットにemployees5ルールが含まれるローカル・データベースのすべての適用プロセスで、employees5ルールを満たすメッセージがhr.change_queueにエンキューされなくなります。
この項では、適用プロセスで、ポジティブ・ルール・セットで指定されたルールを満たすメッセージ用の実行ディレクティブを設定する手順について説明します。
適用プロセスが、指定されたルールを満たすメッセージを実行しないように指定するには、DBMS_APPLY_ADMパッケージのSET_EXECUTEプロシージャを使用します。具体的には、このプロシージャで、ルールのexecuteパラメータをFALSEに設定します。ルールの実行ディレクティブをFALSEに設定すると、そのルールがポジティブ・ルール・セットに含まれる適用プロセスでは、そのルールを満たすメッセージは実行されません。
たとえば、適用プロセスでルールdepartments8を満たすメッセージが実行されないように指定するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.SET_EXECUTE(
rule_name => 'departments8',
execute => FALSE);
END;
/
このプロシージャは、ルールのアクション・コンテキストを変更して、実行ディレクティブを指定します。ポジティブ・ルール・セットにdepartments8ルールが含まれるローカル・データベースのすべての適用プロセスで、departments8ルールを満たすメッセージは実行されません。したがって、メッセージがLCRの場合、適用プロセスでは、LCRの変更が、関連するデータベース・オブジェクトに対して適用されません。また、適用プロセスでは、このルールを満たすメッセージは適用ハンドラに送信されません。
|
注意:
|
適用プロセスが、指定されたルールを満たすメッセージを実行するように指定するには、DBMS_APPLY_ADMパッケージのSET_EXECUTEプロシージャを使用します。具体的には、このプロシージャでルールのexecuteパラメータをTRUEに設定します。デフォルトでは、メッセージが適用プロセスのネガティブ・ルール・セットのルールを満たしていないことを想定して、適用プロセスのポジティブ・ルール・セットに含まれるルールを満たすメッセージが各適用プロセスで実行されます。したがって、ルールのexecuteパラメータが以前FALSEに設定されていた場合にのみ、TRUEに設定する必要があります。
たとえば、適用プロセスがルールdepartments8を満たすメッセージを実行するように指定するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.SET_EXECUTE(
rule_name => 'departments8',
execute => TRUE);
END;
/
ポジティブ・ルール・セットにdepartments8ルールが含まれるローカル・データベースのすべての適用プロセスで、departments8ルールを満たすメッセージが実行されます。したがって、メッセージがLCRの場合、適用プロセスによって、LCRの変更が、関連するデータベース・オブジェクトに対して適用されます。また、適用プロセスでは、このルールを満たすメッセージは適用ハンドラに送信されます(適用プロセスをそのように設定している場合)。
エラー・ハンドラは、任意の適用プロセスによってデキューされた、指定の表に対する指定の操作を含む行LCRから生成されたエラーを処理します。
次の各項では、エラー・ハンドラの作成、設定および設定解除の手順について説明します。
エラー・ハンドラを作成するには、DBMS_APPLY_ADMパッケージのSET_DML_HANDLERプロシージャを実行して、error_handlerパラメータをTRUEに設定します。
エラー・ハンドラには、次のシグネチャが必要です。
PROCEDURE user_procedure (
message IN ANYDATA,
error_stack_depth IN NUMBER,
error_numbers IN DBMS_UTILITY.NUMBER_ARRAY,
error_messages IN emsg_array);
user_procedureは、プロシージャ名です。各パラメータは必須であり、指定されたデータ型を使用する必要があります。ただし、パラメータ名は変更できます。emsg_arrayパラメータには、VARCHAR2型のPL/SQL表である76文字以上のユーザー定義配列で指定する必要があります。
|
注意: エラー・ハンドラは、SET_DML_HANDLERで指定されたユーザー・プロシージャに関する条件を満たす必要があります。これらの条件の詳細は、Oracle Streamsレプリケーション管理者ガイドを参照してください。 |
エラー・ハンドラの実行結果は、次のいずれかになります。
エラー・ハンドラによって、エラーが正常に解決され、該当する場合は行LCRが適用され、制御が適用プロセスに戻されます。
エラー・ハンドラがエラーの解決に失敗し、エラーが発生します。エラーが発生すると、トランザクションはロールバックされ、エラー・キューに置かれます。
DML操作を再実行する場合は、エラー・ハンドラ・プロシージャで、LCR用のEXECUTEメンバー・プロシージャを実行します。
次の例では、hr.regions表の主キー違反を解決するエラー・ハンドラregions_pk_errorを作成します。宛先データベースでは、ユーザーがhr.regions表に行を挿入し、リモート・ソース・データベースの取得プロセスによって発生したhr.regions表に対する変更が、適用プロセスによって適用されるとします。この環境では、宛先データベースのユーザーが、ソース・データベースから適用された挿入行LCRと同じ主キー値を持つ行を挿入すると、エラーが発生する可能性があります。
この例では、hr.regions表の主キー違反によるエラーごとに次の情報を記録するため、strmadminスキーマにerrorlogという表を作成します。
エラー発生時のタイム・スタンプ
エラーが発生した適用プロセスの名前
エラーの原因となったユーザー(送信者)。これは、取得LCRの場合は取得プロセス名、同期取得によって取得された永続LCRの場合は同期取得名、アプリケーションによってエンキューされた永続LCRおよび永続ユーザー・メッセージの場合はOracle Streams Advanced Queuing(AQ)エージェントの名前です
将来、他のオブジェクトのエラーがログに記録される可能性があるため、DMLの操作が実行されたオブジェクトの名前
DML操作で使用されたコマンドのタイプ
違反となった制約の名前
エラー・メッセージ
エラーの原因となったLCR
このエラー・ハンドラでは、hr.regions表での主キー違反によるエラーのみが解決されます。このタイプのエラーを解決するために、エラー・ハンドラでは、順序を使用して行LCRのregion_id値が変更した後、行LCRを実行して適用します。他のタイプのエラーが発生した場合は、errorlog表に格納した行LCRを使用して手動でエラーを解決できます。
たとえば、エラー・ハンドラでは次のエラーが解決されます。
宛先データベースで、ユーザーがhr.regions表にregion_idの値が6、region_nameの値が'LILLIPUT'の1行を挿入します。
ソース・データベースで、ユーザーがhr.regions表にregion_idの値が6、region_nameの値が'BROBDINGNAG'の1行を挿入します。
ソース・データベースの取得プロセスが、手順2で説明した変更を取得します。
伝播によって、ソース・データベースのキューから宛先データベースの適用プロセスで使用されるキューに、変更を含むLCRが伝播されます。
適用プロセスがLCRを適用すると、主キー違反のためにエラーが発生します。
適用プロセスがエラー・ハンドラを起動して、エラーを処理します。
エラー・ハンドラは、エラーをstrmadmin.errorlog表に記録します。
エラー・ハンドラは、順序を使用してLCR内でregion_id値を変更し、そのLCRを実行して適用します。
regions_pk_errorエラー・ハンドラを作成する手順は、次のとおりです。
SQL*Plusで、データベースにhrユーザーとして接続します。
SQL*Plusでデータベースに接続する方法については、Oracle Database管理者ガイドを参照してください。
新しい主キー値に割り当てるためにエラー・ハンドラで使用される順序を作成します。
CREATE SEQUENCE hr.reg_exception_s START WITH 9000;
この例では、宛先データベースのユーザーはregion_idが9000を超える行をhr.regions表に挿入しないと仮定します。
Oracle Streams管理者に、順序に対するALL権限を付与します。
GRANT ALL ON reg_exception_s TO strmadmin;
データベースにOracle Streams管理者として接続します。
errorlog表を作成します。
CREATE TABLE strmadmin.errorlog( logdate DATE, apply_name VARCHAR2(30), sender VARCHAR2(100), object_name VARCHAR2(32), command_type VARCHAR2(30), errnum NUMBER, errmsg VARCHAR2(2000), text VARCHAR2(2000), lcr SYS.LCR$_ROW_RECORD);
regions_pk_errorプロシージャを含めるパッケージを作成します。
CREATE OR REPLACE PACKAGE errors_pkg AS TYPE emsg_array IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER; PROCEDURE regions_pk_error( message IN ANYDATA, error_stack_depth IN NUMBER, error_numbers IN DBMS_UTILITY.NUMBER_ARRAY, error_messages IN EMSG_ARRAY); END errors_pkg ; /
CREATE OR REPLACE PACKAGE BODY errors_pkg AS
PROCEDURE regions_pk_error (
message IN ANYDATA,
error_stack_depth IN NUMBER,
error_numbers IN DBMS_UTILITY.NUMBER_ARRAY,
error_messages IN EMSG_ARRAY )
IS
reg_id NUMBER;
ad ANYDATA;
lcr SYS.LCR$_ROW_RECORD;
ret PLS_INTEGER;
vc VARCHAR2(30);
apply_name VARCHAR2(30);
errlog_rec errorlog%ROWTYPE ;
ov2 SYS.LCR$_ROW_LIST;
BEGIN
-- Access the error number from the top of the stack.
-- In case of check constraint violation,
-- get the name of the constraint violated.
IF error_numbers(1) IN ( 1 , 2290 ) THEN
ad := DBMS_STREAMS.GET_INFORMATION('CONSTRAINT_NAME');
ret := ad.GetVarchar2(errlog_rec.text);
ELSE
errlog_rec.text := NULL ;
END IF ;
-- Get the name of the sender and the name of the apply process.
ad := DBMS_STREAMS.GET_INFORMATION('SENDER');
ret := ad.GETVARCHAR2(errlog_rec.sender);
apply_name := DBMS_STREAMS.GET_STREAMS_NAME();
-- Try to access the LCR.
ret := message.GETOBJECT(lcr);
errlog_rec.object_name := lcr.GET_OBJECT_NAME() ;
errlog_rec.command_type := lcr.GET_COMMAND_TYPE() ;
errlog_rec.errnum := error_numbers(1) ;
errlog_rec.errmsg := error_messages(1) ;
INSERT INTO strmadmin.errorlog VALUES (SYSDATE, apply_name,
errlog_rec.sender, errlog_rec.object_name, errlog_rec.command_type,
errlog_rec.errnum, errlog_rec.errmsg, errlog_rec.text, lcr);
-- Add the logic to change the contents of LCR with correct values.
-- In this example, get a new region_id number
-- from the hr.reg_exception_s sequence.
ov2 := lcr.GET_VALUES('new', 'n');
FOR i IN 1 .. ov2.count
LOOP
IF ov2(i).column_name = 'REGION_ID' THEN
SELECT hr.reg_exception_s.NEXTVAL INTO reg_id FROM DUAL;
ov2(i).data := ANYDATA.ConvertNumber(reg_id) ;
END IF ;
END LOOP ;
-- Set the NEW values in the LCR.
lcr.SET_VALUES(value_type => 'NEW', value_list => ov2);
-- Execute the modified LCR to apply it.
lcr.EXECUTE(TRUE);
END regions_pk_error;
END errors_pkg;
/
|
注意:
|
|
関連項目: 現行セッションで生成されるタグの値の設定の詳細、およびエラー・ハンドラで処理する特定のエラー・メッセージの詳細は、Oracle Streamsレプリケーション管理者ガイドを参照 |
エラー・ハンドラは、任意の適用プロセスによってデキューされた、指定の表に対する指定の操作を含む行LCRから生成したエラーを処理します。同一の表に対する様々な操作で生成されるエラーを処理するために、表に複数のエラー・ハンドラを指定できます。特定の適用プロセスにエラー・ハンドラを設定できます。また、指定の表に指定の操作を適用するすべての適用プロセスで使用される一般的なエラー・ハンドラとして、エラー・ハンドラを設定することもできます。
エラー・ハンドラを設定するには、DBMS_APPLY_ADMパッケージのSET_DML_HANDLERプロシージャを使用します。このプロシージャを実行してエラー・ハンドラを設定する場合は、error_handlerパラメータをTRUEに設定します。
たとえば、次のプロシージャでは、hr.regions表に対するINSERT操作用のエラー・ハンドラを設定します。したがって、適用プロセスによって、ローカルのhr.regions表に対するINSERT操作を含む行LCRがデキューされ、行LCRがエラーになると、適用プロセスでは、行LCRがstrmadmin.errors_pkg.regions_pk_error PL/SQLプロシージャに送信されて処理されます。エラー・ハンドラでエラーを解決できない場合は、その行LCRと、同じトランザクション内の他のすべての行LCRがエラー・キューに移動されます。
この例では、apply_nameパラメータがNULLに設定されます。したがって、エラー・ハンドラは、データベース内のすべての適用プロセスで使用される汎用エラー・ハンドラになります。
次のプロシージャを実行してエラー・ハンドラを設定します。
BEGIN
DBMS_APPLY_ADM.SET_DML_HANDLER(
object_name => 'hr.regions',
object_type => 'TABLE',
operation_name => 'INSERT',
error_handler => TRUE,
user_procedure => 'strmadmin.errors_pkg.regions_pk_error',
apply_database_link => NULL,
apply_name => NULL);
END;
/
エラー・ハンドラがすでに設定されている場合は、SET_DML_HANDLERプロシージャを実行してエラー・ハンドラを変更できます。
エラー・ハンドラの設定を解除するには、DBMS_APPLY_ADMパッケージのSET_DML_HANDLERプロシージャを使用します。このプロシージャを実行するときは、特定の表に対する特定の操作について、user_procedureパラメータをNULLに設定します。
たとえば、次のプロシージャでは、hr.regions表に対するINSERT操作について、エラー・ハンドラの設定が解除されます。
BEGIN
DBMS_APPLY_ADM.SET_DML_HANDLER(
object_name => 'hr.regions',
object_type => 'TABLE',
operation_name => 'INSERT',
user_procedure => NULL,
apply_name => NULL);
END;
/
|
注意: error_handlerパラメータを指定する必要はありません。 |
次の各項では、適用エラーの再試行と削除の手順について説明します。
|
関連項目:
|
特定のエラー・トランザクション、または適用プロセスのすべてのエラー・トランザクションを再試行できます。場合によっては、エラー・トランザクションを再試行する前に、データベース・オブジェクトに対してDML変更またはDDL変更を行い、1つ以上の適用エラーの原因となった状態を修正する必要があります。また、同じデータベース・オブジェクトに対する変更を取得するように1つ以上の取得プロセスまたは同期取得を構成しているときに、変更の取得が不要になる可能性があります。この場合は、変更を行うセッションのセッション・タグを、取得されない値に設定できます。
|
関連項目: 現行セッションで生成されるタグの値の設定の詳細は、Oracle Streamsレプリケーション管理者ガイドを参照 |
エラー・トランザクションを再試行する場合は、直接実行することも、ユーザー・プロシージャにエラー・トランザクションを送信して変更した後で実行することもできます。次の各項では、各方法の手順について説明します。
|
関連項目: EXECUTE_ERRORプロシージャの詳細は、Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンスを参照 |
適用エラーの原因となった条件を修正した後に、ユーザー・プロシージャを指定せずにDBMS_APPLY_ADMパッケージのEXECUTE_ERRORプロシージャを実行して、トランザクションを再試行できます。この場合、トランザクションはカスタム処理を使用せずに実行されます。
たとえば、トランザクション識別子が5.4.312のトランザクションを再試行するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.EXECUTE_ERROR(
local_transaction_id => '5.4.312',
execute_as_user => FALSE,
user_procedure => NULL);
END;
/
execute_as_userがTRUEの場合は、適用プロセスでは、現行ユーザーのセキュリティ・コンテキスト内でトランザクションが実行されます。execute_as_userがFALSEの場合、適用プロセスでは、トランザクションの元の受信者のセキュリティ・コンテキスト内でトランザクションが実行されます。元の受信者は、エラー発生時にトランザクションを処理していたユーザーです。
いずれの場合も、トランザクションを実行するユーザーには、適用オブジェクトに対するDML変更およびDDL変更を実行するための権限と、任意の適用ハンドラを実行するための権限が必要です。また、このユーザーには、適用プロセスで使用されるキューに対するデキュー権限も必要です。
DBMS_APPLY_ADMパッケージのEXECUTE_ERRORプロシージャを実行してエラー・トランザクションを再試行できます。また、ユーザー・プロシージャを指定して、トランザクションの実行前に、トランザクション内の1つ以上のメッセージを変更することもできます。この変更によって、トランザクションが正常に実行できるはずです。トランザクション内のメッセージは、LCRまたはユーザー・メッセージです。
たとえば、競合のために適用エラーが発生したとします。エラー・トランザクションを検証すると、行LCRのsalary列の古い値が間違っていることが判明しました。具体的には、hr.employees表のemployee_idが197の従業員について、給料の現行の値が、行LCRにおけるこの従業員の給料の古い値と一致していません。hr.employees表で、この従業員の現行の値が3250であるとします。
この場合、次のユーザー・プロシージャで、エラーの原因となった行LCRの給料を変更します。
CREATE OR REPLACE PROCEDURE strmadmin.modify_emp_salary(
in_any IN ANYDATA,
error_record IN DBA_APPLY_ERROR%ROWTYPE,
error_message_number IN NUMBER,
messaging_default_processing IN OUT BOOLEAN,
out_any OUT ANYDATA)
AS
row_lcr SYS.LCR$_ROW_RECORD;
row_lcr_changed BOOLEAN := FALSE;
res NUMBER;
ob_owner VARCHAR2(32);
ob_name VARCHAR2(32);
cmd_type VARCHAR2(30);
employee_id NUMBER;
BEGIN
IF in_any.getTypeName() = 'SYS.LCR$_ROW_RECORD' THEN
-- Access the LCR
res := in_any.GETOBJECT(row_lcr);
-- Determine the owner of the database object for the LCR
ob_owner := row_lcr.GET_OBJECT_OWNER;
-- Determine the name of the database object for the LCR
ob_name := row_lcr.GET_OBJECT_NAME;
-- Determine the type of DML change
cmd_type := row_lcr.GET_COMMAND_TYPE;
IF (ob_owner = 'HR' AND ob_name = 'EMPLOYEES' AND cmd_type = 'UPDATE') THEN
-- Determine the employee_id of the row change
IF row_lcr.GET_VALUE('old', 'employee_id') IS NOT NULL THEN
employee_id := row_lcr.GET_VALUE('old', 'employee_id').ACCESSNUMBER();
IF (employee_id = 197) THEN
-- error_record.message_number should equal error_message_number
row_lcr.SET_VALUE(
value_type => 'OLD',
column_name => 'salary',
column_value => ANYDATA.ConvertNumber(3250));
row_lcr_changed := TRUE;
END IF;
END IF;
END IF;
END IF;
-- Specify that the apply process continues to process the current message
messaging_default_processing := TRUE;
-- assign out_any appropriately
IF row_lcr_changed THEN
out_any := ANYDATA.ConvertObject(row_lcr);
ELSE
out_any := in_any;
END IF;
END;
/
トランザクション識別子が5.6.924のトランザクションを再試行する際、実行前にstrmadminスキーマ内のmodify_emp_salaryプロシージャでトランザクションを処理するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.EXECUTE_ERROR(
local_transaction_id => '5.6.924',
execute_as_user => FALSE,
user_procedure => 'strmadmin.modify_emp_salary');
END;
/
|
注意: プロシージャを実行するユーザーは、DBA_APPLY_ERRORデータ・ディクショナリ・ビューに対するSELECT権限を持っている必要があります。 |
適用プロセスについて、すべての適用エラーの原因となった条件を修正した後に、DBMS_APPLY_ADMパッケージのEXECUTE_ALL_ERRORSプロシージャを実行してすべてのエラー・トランザクションを再試行できます。たとえば、適用プロセスstrm01_applyのすべてのエラー・トランザクションを再試行するには、次のプロシージャを実行します。
BEGIN
DBMS_APPLY_ADM.EXECUTE_ALL_ERRORS(
apply_name => 'strm01_apply',
execute_as_user => FALSE);
END;
/
|
注意: apply_nameパラメータに対してNULLを指定した場合に、複数の適用プロセスが存在すると、すべての適用プロセスのすべての適用エラーが再試行されます。 |
特定のエラー・トランザクションまたは適用プロセスのすべてのエラー・トランザクションを削除できます。
エラー・トランザクションを適用する必要がない場合は、DBMS_APPLY_ADMパッケージのDELETE_ERRORプロシージャを使用して、エラー・キューからトランザクションを削除できます。たとえば、トランザクション識別子が5.4.312のトランザクションを削除するには、次のプロシージャを実行します。
EXEC DBMS_APPLY_ADM.DELETE_ERROR(local_transaction_id => '5.4.312');
すべてのエラー・トランザクションを適用しない場合は、DBMS_APPLY_ADMパッケージのDELETE_ALL_ERRORSプロシージャを実行して、すべてのエラー・トランザクションを削除できます。たとえば、適用プロセスstrm01_applyのすべてのエラー・トランザクションを削除するには、次のプロシージャを実行します。
EXEC DBMS_APPLY_ADM.DELETE_ALL_ERRORS(apply_name => 'strm01_apply');
|
注意: apply_nameパラメータに対してNULLを指定した場合に、複数の適用プロセスが存在すると、すべての適用プロセスのすべての適用エラーが削除されます。 |
既存の適用プロセスを削除するには、DBMS_APPLY_ADMパッケージのDROP_APPLYプロシージャを実行します。たとえば、次のプロシージャでは、適用プロセスstrm02_applyが削除されます。
BEGIN
DBMS_APPLY_ADM.DROP_APPLY(
apply_name => 'strm02_apply',
drop_unused_rule_sets => TRUE);
END;
/
drop_unused_rule_setsパラメータがTRUEに設定されているため、このプロシージャではstrm02_apply適用プロセスで使用されているルール・セットも削除されます。ただし、他のOracle Streamsクライアントで使用されているルール・セットは削除されません。drop_unused_rule_setsパラメータがTRUEに設定されている場合は、適用プロセスのポジティブ・ルール・セットとネガティブ・ルール・セットの両方が削除されることがあります。このプロシージャによってルール・セットが削除された場合、そのルール・セット内のルールのうち、他のルール・セットに含まれていないルールも削除されます。
適用プロセスを削除しようとしたときに、指定した適用プロセスのエラー・キューにエラーが存在すると、エラーが発生します。このため、適用プロセスのエラー・キューにエラーが存在する場合は、適用プロセスを削除する前にエラーを削除します。