Sunday, December 07, 2008

Adding a new table to an existing Oracle Streams Replication environment - second attempt

I breifly read the Oracle document about this topic, and I have successfuly added a new table to the replication by taking the following steps:

1. Create the table at source and destination database.

create table scott.strm_tab2 (
id number,
name varchar2(20),
constraint id_pk primary key(id)
);


2. Turn on supplemental logging for the table at source

ALTER TABLE scott.strm_tab2 ADD SUPPLEMENTAL LOG GROUP id_pk1 (id) ALWAYS;

3. At source database, stop the capture process and propagation process

++ CAPTURE PROCESSES IN DATABASE ++
CAPTURE_NAME : STRMADMIN_CAPTURE
QUEUE_OWNER : STRMADMIN
QUEUE : STREAMS_QUEUE
CAPTURE_TYPE : LOCAL
STATUS : DISABLED
RULE_SET_OWNER : SYS
RSN : RULESET$_17
NEGATIVE_RULE_SET_OWNER :
RSN2 :
CHECKPOINT_RETENTION_TIME : 60
VERSION : 10.2.0.1.0
LOGFILE_ASSIGNMENT : IMPLICIT
ERROR_NUMBER :
STATUS_CHANGE_TIME : 07-dec-2008 14:18:13


++ PROPAGATIONS IN DATABASE ++
PROPAGATION_NAME : STRMADMIN_PROPAGATE
SOURCE_QUEUE_OWNER : STRMADMIN
SOURCE_QUEUE_NAME : STREAMS_QUEUE
SRC GLOBAL NAME : TEST10G.WORLD
DESTINATION_QUEUE_OWNER : STRMADMIN
DESTINATION_QUEUE_NAME : STREAMS_QUEUE
DESTINATION_DBLINK : TEST02DB.WORLD
QUEUE_TO_QUEUE : FALSE
STATUS : ABORTED
ERROR_DATE :
ERROR_MESSAGE :
-----------------


4. At destionation database stop the apply process
++ APPLY INFORMATION ++
APPLY_NAME : STRMADMIN_APPLY
QUEUE_OWNER : STRMADMIN
QUEUE_NAME : STREAMS_QUEUE
APPLY_CAPTURED : YES
STATUS : DISABLED
APPLY_USER : SCOTT
APPLY_TAG : 00
RULE_SET_OWNER : STRMADMIN
RULE_SET_NAME : RULESET$_35
NEGATIVE_RULE_SET_OWNER :
NEGATIVE_RULE_SET_NAME :
APPLY_DATABASE_LINK :
-----------------
++ APPLY PROCESS INFORMATION ++
APPLY_NAME : STRMADMIN_APPLY
MAX_APPLIED_MESSAGE_NUMBER : 10138270879363
STATUS : DISABLED
STATUS_CHANGE_TIME : 07-dec-2008 14:20:47
ERROR_NUMBER :
ERROR_MESSAGE :
-----------------


5. At destination database, add rules for an apply process


BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'SCOTT.STRM_TAB2',
streams_type => 'APPLY',
streams_name => 'STRMADMIN_APPLY',
queue_name => 'STRMADMIN.STREAMS_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'TEST10G.world');
END;
/

6. At source database, add rules for propagation process

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name => 'SCOTT.STRM_TAB2',
streams_name => 'STRMADMIN_PROPAGATE',
source_queue_name => 'STRMADMIN.STREAMS_QUEUE',
destination_queue_name => 'STRMADMIN.STREAMS_QUEUE@TEST02DB.world',
include_dml => true,
include_ddl => true,
source_database => 'TEST10G.world');
END;
/

7. At source database, add rules for capture process

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'SCOTT.STRM_TAB2',
streams_type => 'CAPTURE',
streams_name => 'STRMADMIN_CAPTURE',
queue_name => 'STRMADMIN.STREAMS_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'TEST10G.world');
END;
/

8. At destination database, set the instantiation SCN for the table

8.1 Execute the following to get SCN at source

connect STRMADMIN/STRMADMIN@TEST10G
set serveroutput on
DECLARE
iscn NUMBER; -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_OUTPUT.PUT_LINE ('Instantiation SCN is: ' iscn);
END;
/

8.2 Execute the following with the SCN obtained in 8.1


connect strmadmin/strmadmin@TEST02DB
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
source_object_name => 'SCOTT.STRM_TAB2',
source_database_name => 'TEST10G.world',
instantiation_scn => &iscn);
END;
/

9. At source database start capture process

10. At source database start propagation process


11. At destinationdatabase start apply

12. Test the replciation --- OK DML and DDL

It is still not completely clear to me what was wrong for the steps I have taken yesterday. But it looks like we must stop capture, propagation and apply processes if we add a rule to the rule sets they are using and the order matters - From the doc: "If you perform administrative steps in the wrong order, you can lost LCRs"

Saturday, December 06, 2008

Adding a new table to an existing Oracle Streams Replication environment - A failed attempt

Today I assigned myself a task, which is to add a new table to an existing streams replication. The source database is TEST10G and the destination database is TEST02DB. They both reside in my notebook pc.

The following are all the test steps for today, the task does not succeed.

1. Apply create table DDL on both databases:

create table denis.strm_tab1 (
id number,
name varchar2(20),
constraint id_pk primary key(id)
);


2. Check current capture, propagation processes on the source database


++ CAPTURE PROCESSES IN DATABASE ++
CAPTURE_NAME : STRMADMIN_CAPTURE
QUEUE_OWNER : STRMADMIN
QUEUE : STREAMS_QUEUE
CAPTURE_TYPE : LOCAL
STATUS : ENABLED
RULE_SET_OWNER : SYS
RSN : RULESET$_17
NEGATIVE_RULE_SET_OWNER :
RSN2 :
CHECKPOINT_RETENTION_TIME : 60
VERSION : 10.2.0.1.0
LOGFILE_ASSIGNMENT : IMPLICIT
ERROR_NUMBER :
STATUS_CHANGE_TIME : 30-nov-2008 21:07:57
ERROR_MESSAGE :
-----------------

++ CAPTURE PROCESS SOURCE INFORMATION ++
CAPTURE_NAME : STRMADMIN_CAPTURE
CAPTURE_TYPE : LOCAL
SOURCE_DATABASE : TEST10G.WORLD
FIRST_SCN : 10138270589233
START_SCN : 10138270589233
CAPTURED_SCN : 10138270859114
APPLIED_SCN : 10138270859114
LAST_ENQUEUED_SCN : 10138270865525
REQUIRED_CHECKPOINT_SCN : 10138270830473
MAX_CHECKPOINT_SCN : 10138270859114
SOURCE_DBID : 917147433
SOURCE_RESETLOGS_SCN : 534907
SOURCE_RESETLOGS_TIME : 665622764
LOGMINER_ID : 1
-----------------

++ PROPAGATIONS IN DATABASE ++
PROPAGATION_NAME : STRMADMIN_PROPAGATE
SOURCE_QUEUE_OWNER : STRMADMIN
SOURCE_QUEUE_NAME : STREAMS_QUEUE
SRC GLOBAL NAME : TEST10G.WORLDInstantiating
DESTINATION_QUEUE_OWNER : STRMADMIN
DESTINATION_QUEUE_NAME : STREAMS_QUEUE
DESTINATION_DBLINK : TEST02DB.WORLD
QUEUE_TO_QUEUE : FALSE
STATUS : ENABLED
ERROR_DATE :
ERROR_MESSAGE :



3. Check current apply process on the destioination database


++ APPLY INFORMATION ++
APPLY_NAME : STRMADMIN_APPLY
QUEUE_OWNER : STRMADMIN
QUEUE_NAME : STREAMS_QUEUE
APPLY_CAPTURED : YES
STATUS : ENABLED
APPLY_USER : SCOTT
APPLY_TAG : 00
RULE_SET_OWNER : STRMADMIN
RULE_SET_NAME : RULESET$_35
NEGATIVE_RULE_SET_OWNER :
NEGATIVE_RULE_SET_NAME :
APPLY_DATABASE_LINK :
-----------------

++ APPLY PROCESS INFORMATION ++
APPLY_NAME : STRMADMIN_APPLY
MAX_APPLIED_MESSAGE_NUMBER :
STATUS : ENABLED
STATUS_CHANGE_TIME : 03-dec-2008 15:26:13
ERROR_NUMBER :
ERROR_MESSAGE :
-----------------


4. Execute the following steps at source database
4.1 Turn on supplementapply_vt.sqlal logging for STRM_TAB1 table
ALTER TABLE denis.strm_tab1 ADD SUPPLEMENTAL LOG GROUP id_pk1 (id) ALWAYS;

4.2 Add capture rules the table STRM_TAB1 at the source database:

conn / as sysdba
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'DENIS.STRM_TAB1',
streams_type => 'CAPTURE',
streams_name => 'STRMADMIN_CAPTURE',
queue_name => 'STRMADMIN.STREAMS_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'TEST10G.world');
END;
/

4.3 Add propagation rules for the table STRM_TAB1 at the source database.

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name => 'DENIS.STRM_TAB1',
streams_name => 'STRMADMIN_PROPAGATE',
source_queue_name => 'STRMADMIN.STREAMS_QUEUE',
destination_queue_name => 'STRMADMIN.STREAMS_QUEUE@TEST02DB.world',
include_dml => true,
include_ddl => true, Adding to a Streams Replication Environment
source_database => 'TEST10G.world');
END;
/


5. Execute the following steps at the destination database
5.1 Add apply rules for the table at the destination database

BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'DENIS.STRM_TAB1',
streams_type => 'APPLY',
streams_name => 'STRMADMIN_APPLY',
queue_name => 'STRMADMIN.STREAMS_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'TEST10G.world');
END;
/


5.2 Grant privs to scott

Note: The apply user in existing repliction is scott. It may be better to
have different capture, propagation and apply for different schema, will
explore this later

denis@TEST02DB> grant all on strm_tab1 to scott;

Grant succeeded.


6. Instantiating

6.1 Execute the following to get SCN


connect STRMADMIN/STRMADMIN@TEST10G
set serveroutput on
DECLARE Adding to a Streams Replication Environment
iscn NUMBER; -- Variable to hold instantiation SCN value
BEGIN
iscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
DBMS_OUTPUT.PUT_LINE ('Instantiation SCN is: ' iscn);
END;
/

6.2 Execute the following with the SCN obtained in 6.1

connect strmadmin/strmadmin@TEST02DB
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
source_object_name => 'DENIS.STRM_TAB1',
source_database_name => 'TEST10G.world',
instantiation_scn => &iscn);
END;


7. Test to see if the replication work.
Insert a row into denis.strm_tab1 at source to see what happen at the dest.
Results: At the dest the row did not get inserted.
Verified that the replication for scott.dept still works fine.

8. Troubleshoot:

Execute the health check script at source and destination and review the report. Fixed the instantiating error, however, it is still not working
Tried stop and start capture, propagation and apply process, does not help.


9. Next step: Read documentation, try to fix the problem tommorrow if possible.

Oracle Doc: Adding to a Streams Replication Environment

Performance Tuning Articles on Internet

This post is intended to collect various Oracle performance tuning articles readily availalbe from internet.


Burleson

Adams, S.

Friday, December 05, 2008

Demonstrate the Usage of Cursor Variable in PL/SQL

Reference: Cursor Variables



denis@TEST10G> @cursor_variables.sql
denis@TEST10G> rem Fectching Data
denis@TEST10G> rem
denis@TEST10G> rem Purpose: demonstrate the usage of cursor variable in PL/SQL
denis@TEST10G> rem
denis@TEST10G> rem A cursor variable is a pointer to a cursor. Because cursor
denis@TEST10G> rem variables are pointers, they can be passed and returned as
denis@TEST10G> rem parameters to procedures and functions. A cursor variable
denis@TEST10G> rem can also refer to different cursors in its life time
denis@TEST10G>
denis@TEST10G>
denis@TEST10G> drop table emp_tab purge;

Table dropped.

denis@TEST10G>
denis@TEST10G> create table emp_tab
2 as
3 select
4 rownum empno,
5 object_name ename,
6 mod(rownum, 10) + 1 deptno ,
7 rownum * 100 sal
8 from all_objects
9 where rownum < 100;

Table created.

denis@TEST10G>
denis@TEST10G>
denis@TEST10G> drop table dept_tab purge;

Table dropped.

denis@TEST10G> create table dept_tab
2 as
3 select
4 rownum deptno,
5 'd_' || rownum deptname
6 from all_objects
7 where rownum <=10;

Table created.

denis@TEST10G>
denis@TEST10G>
denis@TEST10G> -- the following package defines a PL/SQL cursor variable type Emp_Val_cv_type,
denis@TEST10G> -- and two procedures
denis@TEST10G> -- The first procedure, Open_emp_cv, opens the cursor variable using a bind
denis@TEST10G> -- variable in the WHERE clause. The second procedure, Fetch_emp_data, fetches
denis@TEST10G> -- rows from the Emp_tab table using the cursor variable
denis@TEST10G>
denis@TEST10G>
denis@TEST10G> create or replace package emp_data as
2 type emp_val_cv_type is ref cursor return emp_tab%rowtype;
3 procedure open_emp_cv (emp_cv in out emp_val_cv_type,
4 dept_number in integer);
5 procedure fetch_emp_data (emp_cv in emp_val_cv_type,
6 emp_row out emp_tab%rowtype);
7 end emp_data;
8 /

Package created.

denis@TEST10G>
denis@TEST10G> create or replace package body emp_data as
2 procedure open_emp_cv (emp_cv in out emp_val_cv_type,
3 dept_number in integer) is
4 begin
5 open emp_cv for select * from emp_tab where deptno = dept_number;
6 end open_emp_cv;
7 procedure fetch_emp_data (emp_cv in emp_val_cv_type,
8 emp_row out emp_tab%rowtype) is
9 begin
10 fetch emp_cv into emp_row;
11 end fetch_emp_data;
12 end emp_data;
13 /

Package body created.

denis@TEST10G>
denis@TEST10G>
denis@TEST10G> -- The following code shows how to call emp_data package
denis@TEST10G> -- procedures from a PL/SQL bock:
denis@TEST10G>
denis@TEST10G>
denis@TEST10G> declare
2 -- delcare a cursor variable
3 emp_curs emp_data.emp_val_cv_type;
4 dept_number dept_tab.deptno%type;
5 emp_row emp_tab%rowtype;
6 begin
7 dept_number := 6;
8 -- open the cursor using a variable
9 emp_data.open_emp_cv(emp_curs, dept_number);
10 -- fetch the data and display it
11 loop
12 emp_data.fetch_emp_data(emp_curs, emp_row);
13 exit when emp_curs%notfound;
14 dbms_output.put_line(rpad(emp_row.ename, 20) || ' ' || lpad(emp_row.sal, 20));
15 end loop;
16 end;
17 /
C_COBJ# 500
I_CON1 1500
I_UNDO2 2500
C_USER# 3500
I_COL3 4500
I_PROXY_ROLE_DATA$_2 5500
I_SUPEROBJ1 6500
IDL_SB4$ 7500
TRIGGERJAVAM$ 8500
PROPS$ 9500

PL/SQL procedure successfully completed.

Wednesday, December 03, 2008

Set up a Simple Oracle Streams Replication

Based on the Metalink Note: 224255.1 : "Steps To Setup Replication Using Oracle Streams", I was trying to set up a streams replicatin for the scott.dept table from a soruce datbase TEST10G to a destination database TEST02DB. Both databases are 10g and on my notebook computer. However my first attempt was not successfuly. When I inserted a row into the source table, nothing happens in the destionation table.

Oracle Metalink Note: 273674.1: "Streams Configuration Report and Health Check Script" provides a script that can be used to retrieve all the infomation related to the Streams configuration and perform health check. I used this script to generate the report for the TEST10G and TEST02BD. As expected, the report shows that the setup for the Apply process in the destinaton database is not correct. The source database should use the global name. The global name of source database is TEST10G.world, however in the report the source database is specified by TEST10G.

Firstly, I issued the following statement in the destionatin database as strmadmin
BEGIN
DBMS_STREAMS_ADM.remove_streams_configuration;
END;
/

Then I redo the step 2.4, 2.5, 2.6 and 4.2 as described in the Note: 273674.1. After that I inserted a row in the source scott.dept table and I see the same row got inserted into the destination table also. Replication is now working ...