Overview of the Multiple Source Databases Example

This example illustrates using Streams to replicate data for a schema among three Oracle databases. DML and DDL changes made to tables in the hr schema are captured at all databases in the environment and propagated to each of the other databases in the environment.

As illustrated in Figure 23-1, all of the databases will contain the hr schema when the example is complete. However, at the beginning of the example, the hr schema exists only at mult1.net. During the example, you instantiate the hr schema at mult2.net and mult3.net.

In this example, Streams is used to perform the following series of actions:

After instantiation, the capture process at each database captures DML and DDL changes for all of the tables in the hr schema and enqueues them into a local queue.

Each database propagates these changes to all of the other databases in the environment.

The apply process at each database applies changes in the hr schema received from the other databases in the environment.

This example uses only one queue for each database, but you can use multiple queues for each database if you want to separate changes from different source databases. In addition, this example avoids sending changes back to their source database by using the default apply tag for the apply processes. When you create an apply process, the changes applied by the apply process have redo entries with a tag of '00' (double zero) by default. These changes are not recaptured because, by default, rules created by the DBMS_STREAMS_ADM package have an is_null_tag()='Y' condition by default, and this condition ensures that each capture process captures a change in a redo entry only if the tag for the redo entry is NULL.

Prerequisites

The following prerequisites must be completed before you begin the example in this chapter.

Set the following initialization parameters to the values indicated at each database in the Streams environment:

AQ_TM_PROCESSES: This parameter establishes queue monitor processes. Values from 1 to 10 specify the number of queue monitor processes created to monitor the messages. If AQ_TM_PROCESSES is not specified or is set to 0, then the queue monitor processes are not created. In this example, AQ_TM_PROCESSES should be set to at least 1.

Setting the parameter to 1 or more starts the specified number of queue monitor processes. These queue monitor processes are responsible for managing time-based operations of messages such as delay and expiration, cleaning up retained messages after the specified retention time, and cleaning up consumed messages if the retention time is 0.

GLOBAL_NAMES: This parameter must be set to true. Make sure the global names of the databases are mult1.net, mult2.net, and mult3.net.

JOB_QUEUE_PROCESSES: This parameter must be set to at least 2 because each database propagates events. It should be set to the same value as the maximum number of jobs that can run simultaneously plus one.

COMPATIBLE: This parameter must be set to 9.2.0 or higher.

LOG_PARALLELISM: This parameter must be set to 1 because each database that captures events.

Attention:

You may need to modify other initialization parameter settings for this example to run properly.

Set Up Users and Create Queues and Database Links

This section illustrates how to set up users and create queues and database links for a Streams replication environment that includes three Oracle databases. The remaining parts of this example depend on the users and queues that you configure in this section.

Complete the following steps to set up the users and to create the streams_queue at all of the databases.

If you are viewing this document online, then you can copy the text from the "BEGINNING OF SCRIPT" line on this page to the next "END OF SCRIPT" line into a text editor and then edit the text to create a script for your environment. Run the script with SQL*Plus on a computer that can connect to all of the databases in the environment.

Step 3 Create an Alternate Tablespace for the LogMiner Tables at mult1.net

By default, the LogMiner tables are in the SYSTEM tablespace, but the SYSTEM tablespace may not have enough space for these tables once a capture process starts to capture changes. Therefore, you must create an alternate tablespace for the LogMiner tables.

Step 4 Set Up Users at mult1.net

Create the Streams administrator named strmadmin and grant this user the necessary privileges. These privileges enable the user to manage queues, execute subprograms in packages related to Streams, create rule sets, create rules, and monitor the Streams environment by querying data dictionary views and queue tables. You may choose a different name for this user.

Note:

To ensure security, use a password other than strmadminpw for the Streams administrator.

The SELECT_CATALOG_ROLE is not required for the Streams administrator. It is granted in this example so that the Streams administrator can monitor the environment easily.

If you plan to use the Streams tool in Oracle Enterprise Manager, then grant the Streams administrator SELECTANYDICTIONARY privilege, in addition to the privileges shown in this step.

Step 5 Create the Streams Queue at mult1.net

Connect as the Streams administrator at mult1.net.

*/
CONNECT strmadmin/strmadminpw@mult1.net
/*

Run the SET_UP_QUEUE procedure to create a queue named streams_queue at mult1.net. This queue will function as the Streams queue by holding the changes that will be applied at this database and the changes that will be propagated to other databases.

Running the SET_UP_QUEUE procedure performs the following actions:

Creates a queue table named streams_queue_table. This queue table is owned by the Streams administrator (strmadmin) and uses the default storage of this user.

Creates a queue named streams_queue owned by the Streams administrator (strmadmin).

Starts the queue.

*/
EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();
/*

Step 6 Create the Database Links at mult1.net

Create database links from the current database to the other databases in the environment.

Create a trigger for each table in the hr schema to insert the time of a transaction for each row inserted or updated by the transaction.

*/
CREATE OR REPLACE TRIGGER hr.insert_time_countries
BEFORE
INSERT OR UPDATE ON hr.countries FOR EACH ROW
BEGIN
-- Consider time synchronization problems. The previous update to this
-- row may have originated from a site with a clock time ahead of the
-- local clock time.
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_departments
BEFORE
INSERT OR UPDATE ON hr.departments FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_employees
BEFORE
INSERT OR UPDATE ON hr.employees FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_job_history
BEFORE
INSERT OR UPDATE ON hr.job_history FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_jobs
BEFORE
INSERT OR UPDATE ON hr.jobs FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_locations
BEFORE
INSERT OR UPDATE ON hr.locations FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
CREATE OR REPLACE TRIGGER hr.insert_time_regions
BEFORE
INSERT OR UPDATE ON hr.regions FOR EACH ROW
BEGIN
IF :OLD.TIME IS NULL OR :OLD.TIME < SYSTIMESTAMP THEN
:NEW.TIME := SYSTIMESTAMP;
ELSE
:NEW.TIME := :OLD.TIME + 1 / 86400;
END IF;
END;
/
/*

Step 8 Create an Alternate Tablespace for the LogMiner Tables at mult2.net

By default, the LogMiner tables are in the SYSTEM tablespace, but the SYSTEM tablespace may not have enough space for these tables once a capture process starts to capture changes. Therefore, you must create an alternate tablespace for the LogMiner tables.

Step 9 Set Up Users at mult2.net

Create the Streams administrator named strmadmin and grant this user the necessary privileges. These privileges enable the user to manage queues, execute subprograms in packages related to Streams, create rule sets, create rules, and monitor the Streams environment by querying data dictionary views and queue tables. You may choose a different name for this user.

Note:

To ensure security, use a password other than strmadminpw for the Streams administrator.

The SELECT_CATALOG_ROLE is not required for the Streams administrator. It is granted in this example so that the Streams administrator can monitor the environment easily.

If you plan to use the Streams tool in Oracle Enterprise Manager, then grant the Streams administrator SELECTANYDICTIONARY privilege, in addition to the privileges shown in this step.

Step 10 Create the Streams Queue at mult2.net

Connect as the Streams administrator at mult2.net.

*/
CONNECT strmadmin/strmadminpw@mult2.net
/*

Run the SET_UP_QUEUE procedure to create a queue named streams_queue at mult2.net. This queue will function as the Streams queue by holding the changes that will be applied at this database and the changes that will be propagated to other databases.

Running the SET_UP_QUEUE procedure performs the following actions:

Creates a queue table named streams_queue_table. This queue table is owned by the Streams administrator (strmadmin) and uses the default storage of this user.

Creates a queue named streams_queue owned by the Streams administrator (strmadmin).

Starts the queue.

*/
EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();
/*

Step 11 Create the Database Links at mult2.net

Create database links from the current database to the other databases in the environment.

Step 12 Drop All of the Tables in the hr Schema at mult2.net

This example illustrates instantiating the tables in the hr schema at mult2.net by exporting these tables from mult1.net and importing them into mult2.net. You must drop the tables in the hr schema at mult2.net for the instantiation portion of this example to work properly.

Attention:

If you complete the following steps and drop the tables in the hr schema at mult2.net, then you should complete the remaining steps of this example to reinstantiate the hr schema. If the hr schema does not exist in an Oracle database, then some examples in the Oracle documentation set may fail.

Step 13 Create an Alternate Tablespace for the LogMiner Tables at mult3.net

By default, the LogMiner tables are in the SYSTEM tablespace, but the SYSTEM tablespace may not have enough space for these tables once a capture process starts to capture changes. Therefore, you must create an alternate tablespace for the LogMiner tables.

Step 14 Set Up Users at mult3.net

Create the Streams administrator named strmadmin and grant this user the necessary privileges. These privileges enable the user to manage queues, execute subprograms in packages related to Streams, create rule sets, create rules, and monitor the Streams environment by querying data dictionary views and queue tables. You may choose a different name for this user.

Note:

To ensure security, use a password other than strmadminpw for the Streams administrator.

The SELECT_CATALOG_ROLE is not required for the Streams administrator. It is granted in this example so that the Streams administrator can monitor the environment easily.

If you plan to use the Streams tool in Oracle Enterprise Manager, then grant the Streams administrator SELECTANYDICTIONARY privilege, in addition to the privileges shown in this step.

Step 15 Create the Streams Queue at mult3.net

Connect as the Streams administrator at mult3.net.

*/
CONNECT strmadmin/strmadminpw@mult3.net
/*

Run the SET_UP_QUEUE procedure to create a queue named streams_queue at mult3.net. This queue will function as the Streams queue by holding the changes that will be applied at this database and the changes that will be propagated to other databases.

Running the SET_UP_QUEUE procedure performs the following actions:

Creates a queue table named streams_queue_table. This queue table is owned by the Streams administrator (strmadmin) and uses the default storage of this user.

Creates a queue named streams_queue owned by the Streams administrator (strmadmin).

Starts the queue.

*/
EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();
/*

Step 16 Create the Database Links at mult3.net

Create database links from the current database to the other databases in the environment.

Step 17 Drop All of the Tables in the hr Schema at mult3.net

This example illustrates instantiating the tables in the hr schema at mult3.net by exporting these tables from mult1.net and importing them into mult3.net. You must drop the tables in the hr schema at mult3.net for the instantiation portion of this example to work properly.

Attention:

If you complete the following steps and drop the tables in the hr schema at mult3.net, then you should complete the remaining steps of this example to reinstantiate the hr schema. If the hr schema does not exist in an Oracle database, then some examples in the Oracle documentation set may fail.

If you are viewing this document online, then you can copy the text from the "BEGINNING OF SCRIPT" line on this page to the next "END OF SCRIPT" line into a text editor and then edit the text to create a script for your environment. Run the script with SQL*Plus on a computer that can connect to all of the databases in the environment.

For convenience, this example includes the primary key column(s) for each table and the columns used for update conflict resolution in a single unconditional log group. You may choose to place the primary key column(s) for each table in an unconditional log group and the columns used for update conflict resolution in a conditional log group.

You do not need to specify supplemental logging explicitly at mult2.net and mult3.net in this example. When you use export/import to instantiate the tables in the hr schema at these databases later in this example, the supplemental logging specifications at mult1.net are retained at mult2.net and mult3.net.

Step 5 Specify hr as the Apply User for Each Apply Process at mult1.net

In this example, the hr user owns all of the database objects for which changes are applied by the apply process at this database. Therefore, hr already has the necessary privileges to change these database objects, and it is convenient to make hr the apply user.

When the apply process was created in the previous step, the Streams administrator strmadmin was specified as the apply user by default, because strmadmin ran the procedure that created the apply process. Instead of specifying hr as the apply user, you could retain strmadmin as the apply user, but then you must grant strmadmin privileges on all of the database objects for which changes are applied and privileges to execute all user procedures used by the apply process. In an environment where an apply process applies changes to database objects in multiple schemas, it may be more convenient to use the Streams administrator as the apply user.

Step 7 Configure Latest Time Conflict Resolution at mult1.net

Specify an update conflict handler for each table in the hr schema. For each table, designate the time column as the resolution column for a MAXIMUM conflict handler. When an update conflict occurs, such an update conflict handler applies the transaction with the latest (or greater) time and discards the transaction with the earlier (or lesser) time. The column lists for each table do not include the primary key because this example assumes that primary key values are never updated.

Step 10 Set the Instantiation SCN for mult2.net at the Other Databases

In this example, the hr schema already exists at all of the databases. The tables in the schema exist only at mult1.net until they are instantiated at mult2.net and mult3.net in Step 21. The instantiation is done using an export of the tables from mult1.net. These export/import operations set the schema instantiation SCNs for mult1.net at mult2.net and mult3.net automatically.

However, the instantiation SCNs for mult2.net and mult3.net are not set automatically at the other sites in the environment. This step sets the schema instantiation SCN for mult2.net manually at mult1.net and mult3.net. The current SCN at mult2.net is obtained by using the GET_SYSTEM_CHANGE_NUMBER function in the DBMS_FLASHBACK package at mult2.net. This SCN is used at mult1.net and mult3.net to run the SET_SCHEMA_INSTANTIATION_SCN procedure in the DBMS_APPLY_ADM package.

The SET_SCHEMA_INSTANTIATION_SCN procedure controls which DDL LCRs for a schema are ignored by an apply process and which DDL LCRs for a schema are applied by an apply process. If the commit SCN of a DDL LCR for a database object in a schema from a source database is less than or equal to the instantiation SCN for that database object at some destination database, then the apply process at the destination database disregards the DDL LCR. Otherwise, the apply process applies the DDL LCR.

Because you are running the SET_SCHEMA_INSTANTIATION_SCN procedure before the tables are instantiated at mult2.net, and because the local capture process is configured already, you do not need to run the SET_TABLE_INSTANTIATION_SCN for each table after the instantiation. In this example, an apply process at both mult1.net and mult3.net will apply transactions to the tables in the hr schema with SCNs that were committed after the SCN obtained in this step.

Note:

In a case where you are instantiating a schema that does not exist, you can set the global instantiation SCN instead of the schema instantiation SCN.

In a case where the tables are instantiated before you set the instantiation SCN, you must set the schema instantiation SCN and the instantiation SCN for each table in the schema.

Step 12 Specify hr as the Apply User for Each Apply Process at mult2.net

In this example, the hr user owns all of the database objects for which changes are applied by the apply process at this database. Therefore, hr already has the necessary privileges to change these database objects, and it is convenient to make hr the apply user.

When the apply process was created in the previous step, the Streams administrator strmadmin was specified as the apply user by default, because strmadmin ran the procedure that created the apply process. Instead of specifying hr as the apply user, you could retain strmadmin as the apply user, but then you must grant strmadmin privileges on all of the database objects for which changes are applied and privileges to execute all user procedures used by the apply process. In an environment where an apply process applies changes to database objects in multiple schemas, it may be more convenient to use the Streams administrator as the apply user.

Step 16 Set the Instantiation SCN for mult3.net at the Other Databases

In this example, the hr schema already exists at all of the databases. The tables in the schema exist only at mult1.net until they are instantiated at mult2.net and mult3.net in Step 21. The instantiation is done using an export of the tables from mult1.net. These export/import operations set the schema instantiation SCNs for mult1.net at mult2.net and mult3.net automatically.

However, the instantiation SCNs for mult2.net and mult3.net are not set automatically at the other sites in the environment. This step sets the schema instantiation SCN for mult3.net manually at mult1.net and mult2.net. The current SCN at mult3.net is obtained by using the GET_SYSTEM_CHANGE_NUMBER function in the DBMS_FLASHBACK package at mult3.net. This SCN is used at mult1.net and mult2.net to run the SET_SCHEMA_INSTANTIATION_SCN procedure in the DBMS_APPLY_ADM package.

The SET_SCHEMA_INSTANTIATION_SCN procedure controls which DDL LCRs for a schema are ignored by an apply process and which DDL LCRs for a schema are applied by an apply process. If the commit SCN of a DDL LCR for a database object in a schema from a source database is less than or equal to the instantiation SCN for that database object at some destination database, then the apply process at the destination database disregards the DDL LCR. Otherwise, the apply process applies the DDL LCR.

Because you are running the SET_SCHEMA_INSTANTIATION_SCN procedure before the tables are instantiated at mult3.net, and because the local capture process is configured already, you do not need to run the SET_TABLE_INSTANTIATION_SCN for each table after the instantiation. In this example, an apply process at both mult1.net and mult2.net will apply transactions to the tables in the hr schema with SCNs that were committed after the SCN obtained in this step.

Note:

In a case where you are instantiating a schema that does not exist, you can set the global instantiation SCN instead of the schema instantiation SCN.

In a case where the tables are instantiated before you set the instantiation SCN, you must set the schema instantiation SCN and the instantiation SCN for each table in the schema.

Step 18 Specify hr as the Apply User for Each Apply Process at mult3.net

In this example, the hr user owns all of the database objects for which changes are applied by the apply process at this database. Therefore, hr already has the necessary privileges to change these database objects, and it is convenient to make hr the apply user.

When the apply process was created in the previous step, the Streams administrator strmadmin was specified as the apply user by default, because strmadmin ran the procedure that created the apply process. Instead of specifying hr as the apply user, you could retain strmadmin as the apply user, but then you must grant strmadmin privileges on all of the database objects for which changes are applied and privileges to execute all user procedures used by the apply process. In an environment where an apply process applies changes to database objects in multiple schemas, it may be more convenient to use the Streams administrator as the apply user.

Step 21 Instantiate the hr Schema at mult2.net and mult3.net

Open a different window and export the schema at mult1.net that will be instantiated at mult2.net and mult3.net. Make sure you set the OBJECT_CONSISTENT export parameter to y when you run the export command. Also, make sure no DDL changes are made to the objects being exported during the export.

*/
PAUSE Press <RETURN> to continue when the export is complete in the other window
that you opened.
/*

Transfer the export dump file hr_schema.dmp to the destination databases. In this example, the destination databases are mult2.net and mult3.net.

You can use binary FTP or some other method to transfer the export dump file to the destination database. You may need to open a different window to transfer the file.

*/
PAUSE Press <RETURN> to continue after transferring the dump file to all of the
other databases in the environment.
/*

In a different window, connect to the computer that runs the mult2.net database and import the export dump file hr_schema.dmp to instantiate the tables in the mult2.net database. You can use telnet or remote login to connect to the computer that runs mult2.net.

When you run the import command, make sure you set the STREAMS_INSTANTIATION import parameter to y. This parameter ensures that the import records export SCN information for each object imported.

Also, make sure no changes are made to the tables in the schema being imported at the destination database (mult2.net) until the import is complete and the capture process is created.

*/
PAUSE Press <RETURN> to continue after the import is complete at mult2.net.
/*

In a different window, connect to the computer that runs the mult3.net database and import the export dump file hr_schema.dmp to instantiate the tables in the mult3.net database.

After you connect to mult3.net, perform the import in the same way that you did for mult2.net.

*/
PAUSE Press <RETURN> to continue after the import is complete at mult3.net.
/*

Step 22 Configure Latest Time Conflict Resolution at mult2.net

Connect to mult2.net as the strmadmin user.

*/
CONNECT strmadmin/strmadminpw@mult2.net
/*

Specify an update conflict handler for each table in the hr schema. For each table, designate the time column as the resolution column for a MAXIMUM conflict handler. When an update conflict occurs, such an update conflict handler applies the transaction with the latest (or greater) time and discards the transaction with the earlier (or lesser) time.

Step 24 Configure Latest Time Conflict Resolution at mult3.net

Connect to mult3.net as the strmadmin user.

*/
CONNECT strmadmin/strmadminpw@mult3.net
/*

Specify an update conflict handler for each table in the hr schema. For each table, designate the time column as the resolution column for a MAXIMUM conflict handler. When an update conflict occurs, such an update conflict handler applies the transaction with the latest (or greater) time and discards the transaction with the earlier (or lesser) time.

Step 30 Check the Spool Results

Check the streams_mult.out spool file to ensure that all actions finished successfully after this script is completed.

*/
SET ECHO OFF
SPOOL OFF
/*************************** END OF SCRIPT ******************************/

Make DML and DDL Changes to Tables in the hr Schema

You can make DML and DDL changes to the tables in the hr schema at any of the databases in the environment. These changes will be replicated to the other databases in the environment, and you can run queries to view the replicated data.

For example, complete the following steps to make DML changes to the hr.employees table at mult1.net and mult2.net. To see the update conflict handler you configured earlier resolve an update conflict, you can make a change to the same row in these two databases and commit the changes at nearly the same time. Then, you can query the hr.employees table at each database in the environment to confirm that the changes were captured, propagated, and applied correctly.

You can also make a DDL change to the hr.jobs table at mult3.net and then confirm that the change was captured at mult3.net, propagated to the other databases in the environment, and applied at these databases.

Step 1 Make a DML Change to hr.employees at mult.net and mult2.net

Make the following changes. Try to commit them at nearly the same time, but commit the change at mult2.net after you commit the change at mult1.net.

Step 2 Alter the hr.jobs Table at mult3.net

Step 3 Query the hr.employees Table at Each Database

After some time passes to allow for capture, propagation, and apply of the changes performed in Step 1, run the following query to confirm that the UPDATE changes have been applied at each database.

CONNECT hr/hr@mult1.net
SELECT salary FROM hr.employees WHERE employee_id=206;
CONNECT hr/hr@mult2.net
SELECT salary FROM hr.employees WHERE employee_id=206;
CONNECT hr/hr@mult3.net
SELECT salary FROM hr.employees WHERE employee_id=206;
All of the queries should show 10000 for the value of the salary.

Step 4 Describe the hr.jobs Table at Each Database

After some time passes to allow for capture, propagation, and apply of the change performed in Step 2, describe the hr.jobs table at each database to confirm that the ALTERTABLE change was propagated and applied correctly.

CONNECT hr/hr@mult1.net
DESC hr.jobs
CONNECT hr/hr@mult2.net
DESC hr.jobs
CONNECT hr/hr@mult3.net
DESC hr.jobs
Each database should show job_name as the second column in the table.