In this post, you'll find an easy to reproduce sample application. You'll create a User Define Type (UDT) with a BFILE (i.e. a file located outside the database on a file system or in ASM). Once done, you'll create an instance of that type, you'll wrap it in an ANYDATA type and will share it between databases with Streams. You'll figure out that, not only the message with a BFILE locator, but also the corresponding file will be transferred from the source database to the destination database.
This post is made of the following sections:
- Step 1: Configure Databases, Streams Administrators and Directories
- Step 2: Configure Directories and the User Defined Type
- Step 3: Create the Database Link and the Propagation Between the Queues
- Step 4: Create A Streams Message Consumer and a Dequeue Program
- Step 5: Test The Streams configuration is working
- Step 6: Create a File and Transfer It with Streams
- Step 7: Troubleshooting
- Step 8: Clean-up the environment
Step 1: Configure Databases and Streams Administrators
If you read this blog or the documentation, you've seen it dozens of time already! In order for Streams to work, you must setup a Streams Administrator, a queue and, though it's not mandatory, it's strongly recommended to set theglobal_names
parameter of the two databases to TRUE
. In this sample application, you'll assume we have 2 databases called BLACK
, the source, and WHITE
, the destination. You'll find below a table with the commands to run on the 2 databases to setup the Streams Administrator and the parameters:On BLACK | On WHITE |
---|---|
select * from global_name; | select * from global_name; |
connect / as sysdba | connect / as sysdba |
Note:
Because we don't use any Streams capture process, those databases don't have to be in archivelog mode.
Step 2: Configure Directories and the User Defined Type
Once the Streams Administrator created, you'll create a directory with the same name on the 2 databases as well as a User Defined Type. To allow the instances associated with the 2 databases to run on the same server, the directory path forBLACK
differs from the directory path for WHITE
:On BLACK | On WHITE |
---|---|
!mkdir -p /tmp/black | !mkdir -p /tmp/white |
connect strmadmin/strmadmin | connect strmadmin/strmadmin |
Step 3: Create the Database Link and the Propagation Between the Queues
Make sure you can add an aliasWHITE
to connect to the WHITE
database in the Oracle*Net configuration of the BLACK
database (e.g. in the tnsnames.ora
file). Once done, you can create a database link from BLACK
to WHITE
and create a Propagation process to send messages from the source to the destination database. Connect to the BLACK
and run the script below:connect strmadmin/strmadmin
select * from GLOBAL_NAME;
GLOBAL_NAME
----------
BLACK
CREATE DATABASE LINK WHITE
connect to STRMADMIN
identified by strmadmin
using 'WHITE';
BEGIN
DBMS_PROPAGATION_ADM.CREATE_PROPAGATION(
propagation_name => 'bfile_propagation',
source_queue => 'strmadmin.streams_queue',
destination_queue => 'strmadmin.streams_queue',
destination_dblink => 'white',
rule_set_name => null,
queue_to_queue => TRUE);
END;
/
Step 4: Create A Streams Message Consumer And A Dequeue Program
You can now configure theWHITE
database so that a program of yours dequeues messages from its Streams queue. The script below creates a Streams DEQUEUE client and execute an anonymous PL/SQL block that receives and removes any messages (if ID>0
):connect strmadmin/strmadmin
begin
DBMS_STREAMS_ADM.ADD_MESSAGE_RULE (
message_type => 'strmadmin.demotyp',
rule_condition => ':MSG.ID > 0',
streams_type => 'DEQUEUE',
streams_name => 'demostrm',
queue_name => 'strmadmin.streams_queue');
end;
/
select streams_name,
queue_owner||'.'||queue_name queue
from DBA_STREAMS_MESSAGE_CONSUMERS;
set serveroutput on
declare
v_demotyp demotyp;
v_any anydata;
v_out pls_integer;
begin
dbms_streams_messaging.dequeue(
queue_name => 'strmadmin.streams_queue',
streams_name => 'demostrm',
payload => v_any,
dequeue_mode => 'REMOVE',
navigation => 'NEXT TRANSACTION',
wait => DBMS_STREAMS_MESSAGING.FOREVER);
v_out := v_any.getobject(v_demotyp);
dbms_output.put_line('Message Received: '||
to_char(v_demotyp.id));
commit;
end;
/
Step 5: Test The Streams Configuration
You can now test your settings. In order to do it, enqueue a message on theBLACK
side. For this first test, don't "attach" any file to the message; leave myfile
to NULL
:connect strmadmin/strmadminThe program running on the
declare
v_demotyp demotyp:=demotyp(1, null);
v_any anydata;
begin
v_any:=anydata.convertobject(v_demotyp);
dbms_streams_messaging.enqueue(
'strmadmin.streams_queue',
v_any);
end;
/
commit;
WHITE
should display the following line and stop:Message Received: 1
Step 6: Create a File and Transfer It with Streams
You'll perform the same test, but this time with a file attached. Restart the program onWHITE
:select * from GLOBAL_NAME;Create a file that is a multiple of 512 bytes in size on the
GLOBAL_NAME
----------
WHITE
set serveroutput on
declare
v_demotyp demotyp;
v_any anydata;
v_out pls_integer;
begin
dbms_streams_messaging.dequeue(
queue_name => 'strmadmin.streams_queue',
streams_name => 'demostrm',
payload => v_any,
dequeue_mode => 'REMOVE',
navigation => 'NEXT TRANSACTION',
wait => DBMS_STREAMS_MESSAGING.FOREVER);
v_out := v_any.getobject(v_demotyp);
dbms_output.put_line('Message Received: '||
to_char(v_demotyp.id));
commit;
end;
/
BLACK
side, allocate a BFILE
that points to it and send it to WHITE
with Streams:connect strmadmin/strmadminThe program you've restarted on
select * from GLOBAL_NAME;
GLOBAL_NAME
----------
BLACK
!dd if=/dev/zero of=/tmp/black/demo.zero bs=512 count=1
declare
v_demotyp demotyp:=demotyp(2, bfilename('tmp_dir','demo.zero'));
v_any anydata;
begin
v_any:=anydata.convertobject(v_demotyp);
dbms_streams_messaging.enqueue(
'strmadmin.streams_queue',
v_any);
end;
/
commit;
WHITE
should display something like:Message Received: 2And the file should now be present on the
WHITE
side too:!ls -l /tmp/white
total 4
-rw-r----- 1 oracle oinstall 512 2009-08-24 00:25 demo.zero
Step 7: Troubleshooting
Troubleshooting this sample is beyond the scope of the post. However if the configuration is not working, that's very likely it's related to the propagation of the file (the file size, some privileges on the/tmp/white
directory, etc). You can query DBA_PROPAGATION and the queue tables to know more about the status of your message. If there is any error at the propagation level, fix it and you restart the propagation:exec dbms_propagation_adm.stop_propagation('bfile_propagation',true);
exec dbms_propagation_adm.start_propagation('bfile_propagation');
Step 8: Clean-up the environment
As always, leave the database as it was when you've first started. The scripts below removes all the components:On BLACK | On WHITE |
---|---|
connect / as sysdba | connect / as sysdba |
In the next post, we'll get a bit deeper in the troubleshooting part; we'll generate an error with the propagation and we'll see how to fix it. Stay tuned!
No comments:
Post a Comment