Professional Documents
Culture Documents
Streams: Julian Dyke Independent Consultant
Streams: Julian Dyke Independent Consultant
juliandyke.com
Streams
juliandyke.com
Target Database
Propagate LCRs Streams Queue Database Objects
Record Changes
LGWR Log Changes
Dequeue LCRs
Apply Process
Apply Changes
Capture Changes
juliandyke.com
Downstream Database
Streams Queue
Enqueue LCRs
Record Changes
LGWR Log Changes Read Redo Data Online Redo Log ARCn Write Redo Data
juliandyke.com
Downstream Database
Streams Queue Enqueue LCRs Capture Process LGWR Write Redo Data Read Redo Data
juliandyke.com
Streams Preparation
Used two separate servers server1 and server2 Used DBCA to create one database on each server SOURCE and TARGET
juliandyke.com
Streams Preparation
juliandyke.com
Streams Configuration
juliandyke.com
Streams Configuration
EXECUTE DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE( privilege => 'DEQUEUE_ANY', grantee => 'STRMADMIN', admin_option => FALSE);
EXECUTE DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE( privilege => 'MANAGE_ANY', grantee => 'STRMADMIN', admin_option => TRUE); EXECUTE DBMS_AQADM.GRANT_TYPE_ACCESS( user_name => 'STRMADMIN');
juliandyke.com
Streams Configuration
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ, grantee => 'STRMADMIN', grant_option => TRUE);
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ, grantee => 'STRMADMIN', grant_option => TRUE); EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.CREATE_RULE_OBJ, grantee => 'STRMADMIN', grant_option => TRUE);
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.CREATE_ANY_RULE_SET, grantee => 'STRMADMIN', grant_option => TRUE);
10
juliandyke.com
Streams Configuration
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.ALTER_ANY_RULE_SET, grantee => 'STRMADMIN', grant_option => TRUE);
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.EXECUTE_ANY_RULE_SET, grantee => 'STRMADMIN', grant_option => TRUE); EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.CREATE_ANY_RULE, grantee => 'STRMADMIN', grant_option => TRUE);
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.ALTER_ANY_RULE, grantee => 'STRMADMIN', grant_option => TRUE);
11
juliandyke.com
Streams Configuration
And finally...
EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.EXECUTE_ANY_RULE, grantee => 'STRMADMIN', grant_option => TRUE); EXECUTE DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE( privilege => DBMS_RULE_ADM.EXECUTE_ON_EVALUATION_CONTEXT, object_name => 'SYS.STREAMS$_EVALUATION_CONTEXT', grantee => 'STRMADMIN', grant_option => FALSE ); EXECUTE DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE( privilege => DBMS_RULE_ADM.EXECUTE_ANY_EVALUATION_CONTEXT, grantee => 'STRMADMIN', grant_option => TRUE);
EXECUTE DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('STRMADMIN');
12
juliandyke.com
Streams Configuration
EXECUTE DBMS_STREAMS_ADM.SET_UP_QUEUE( queue_table => 'STREAMS_QUEUE', queue_name => 'STREAMS_QUEUE', queue_user => 'STRMADMIN');
CREATE DATABASE LINK TARGET CONNECT TO strmadmin IDENTIFIED BY strmadmin USING 'TARGET';
CREATE DATABASE LINK SOURCE CONNECT TO strmadmin IDENTIFIED BY strmadmin USING 'SOURCE';
13
juliandyke.com
Streams Configuration
DECLARE l_scn number; BEGIN -- Build Logminer dictionary for the capture process DBMS_CAPTURE_ADM.BUILD (l_scn); -- Creates the capture based on the previous build DBMS_CAPTURE_ADM.CREATE_CAPTURE ( queue_name=>'STRMADMIN.STREAMS_QUEUE', capture_name=>'CAPTURE1', checkpoint_retention_time=>7, first_scn=>l_scn ); END; /
14
juliandyke.com
Streams Configuration
DECLARE l_global_name varchar2(255); BEGIN -- Get the global name of the database SELECT global_name INTO l_global_name FROM global_name; -- Adds the SCOTT.EMP to the streams capture rules DBMS_STREAMS_ADM.ADD_TABLE_RULES ( table_name => 'SCOTT.EMP', streams_type => 'CAPTURE', streams_name => 'CAPTURE1', queue_name => 'STRMADMIN.STREAMS_QUEUE', include_dml => TRUE, include_ddl => TRUE, source_database => l_global_name ); END; /
15
juliandyke.com
Streams Configuration
-- Prepare tables for instantiation -- Supplemental logging must be enabled on the tables BEGIN DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION ( table_name => 'SCOTT.EMP', supplemental_logging=>'keys' );
END; /
16
juliandyke.com
Streams Configuration
BEGIN -- Get scn from source l_scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER@SOURCE; --Create a user-named Data Pump job to do a "table-level" import --using a network link l_job_handle := DBMS_DATAPUMP.OPEN ( operation => 'IMPORT', job_mode => 'TABLE', remote_link => 'SOURCE', job_name => 'IMPORT_SCOTT_'||TO_CHAR (SYSDATE,'SSSSS') );
17
juliandyke.com
Streams Configuration
DBMS_DATAPUMP.METADATA_FILTER ( handle => l_job_handle, name => 'NAME_LIST', value => '''EMP''' );
18
juliandyke.com
Streams Configuration
-- Set parameters DBMS_DATAPUMP.SET_PARAMETER ( handle => l_job_handle, name => 'FLASHBACK_SCN', value => l_scn ); DBMS_DATAPUMP.SET_PARAMETER ( handle => l_job_handle, name => 'TABLE_EXISTS_ACTION', value => 'REPLACE' );
19
juliandyke.com
Streams Configuration
20
juliandyke.com
Streams Configuration
DECLARE l_scn number; BEGIN DBMS_STREAMS_ADM.ADD_TABLE_RULES ( table_name => 'SCOTT.EMP', streams_type => 'APPLY', streams_name => 'APPLY1', queue_name => 'STRMADMIN.STREAMS_QUEUE', include_dml => TRUE, include_ddl => TRUE, source_database => 'SOURCE' ); END; /
21
juliandyke.com
Streams Configuration
DECLARE l_scn number; BEGIN l_scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER (); -- Set the table instantiation SCN DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN ( source_object_name => 'SCOTT.EMP', source_database_name => 'SOURCE', instantiation_scn => l_scn ); END; /
22
juliandyke.com
Streams Configuration
BEGIN -- add the schema to the propagation rules DBMS_STREAMS_ADM.ADD_SCHEMA_PROPAGATION_RULES ( schema_name => 'SCOTT', streams_name => 'PROPAGATE1', source_queue_name => 'STRMADMIN.STREAMS_QUEUE', destination_queue_name => 'STRMADMIN.STREAMS_QUEUE@TARGET', include_dml => TRUE, include_ddl => TRUE, queue_to_queue => TRUE, source_database => 'SOURCE' ); END; /
23
juliandyke.com
Streams Configuration
24
juliandyke.com
25
Two types of LCR row LCR SYS.LCR$_ROW_RECORD DDL LCR SYS.LCR$_DDL_RECORD Enqueued into an ANYDATA queue Can be Captured by capture process Constructed and enqueued by user or application Can be modified by Rule-based transformation Apply process
26
juliandyke.com
27
juliandyke.com
28
juliandyke.com
29
juliandyke.com
30
juliandyke.com
31
juliandyke.com
Inserting a row (1 of 3)
INSERT INTO dept (deptno,dname,loc) VALUES (50,'IT','LONDON');
DECLARE l_deptno l_dname l_loc l_newvals l_row
juliandyke.com
Inserting a row (2 of 3)
l_dname := SYS.LCR$_ROW_UNIT ( 'DNAME', ANYDATA.ConvertVarchar2 ('IT'), DBMS_LCR.NOT_A_LOB, NULL, NULL ); l_loc := SYS.LCR$_ROW_UNIT ( 'LOC', ANYDATA.ConvertVarchar2 ('LONDON'), DBMS_LCR.NOT_A_LOB, NULL, NULL ); l_newvals := SYS.LCR$_ROW_LIST (l_deptno,l_dname,l_loc);
33
juliandyke.com
Inserting a row (3 of 3)
-- Construct the LCR l_row := SYS.LCR$_ROW_RECORD.CONSTRUCT ( source_database_name => 'SOURCE', command_type => 'INSERT', object_owner => 'SCOTT', object_name => 'DEPT', old_values => NULL, new_values => l_new_vals ); DBMS_STREAMS_MESSAGING.ENQUEUE ( queue_name => 'QUEUE2', payload => ANYDATA.ConvertObject (l_row) );
34
juliandyke.com
Updating a row (1 of 3)
UPDATE dept SET loc = 'READING' WHERE deptno = 50;
DECLARE l_deptno l_old_loc l_new_loc l_oldvals l_newvals l_row
juliandyke.com
Updating a row (2 of 3)
l_old_loc := SYS.LCR$_ROW_UNIT ( 'LOC', ANYDATA.ConvertVarchar2 ('LONDON'), DBMS_LCR.NOT_A_LOB, NULL, NULL );
juliandyke.com
Updating a row (3 of 3)
-- Construct the LCR l_row := SYS.LCR$_ROW_RECORD.CONSTRUCT ( source_database_name => 'SOURCE', command_type => 'UPDATE', object_owner => 'SCOTT', object_name => 'DEPT', old_values => l_old_vals, new_values => l_new_vals ); DBMS_STREAMS_MESSAGING.ENQUEUE ( queue_name => 'QUEUE2', payload => ANYDATA.ConvertObject (l_row) );
37
juliandyke.com
info@juliandyke.com
38
juliandyke.com