Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Henrik.

Asked: December 08, 2016 - 3:05 pm UTC

Last updated: January 03, 2017 - 2:58 pm UTC

Version: 11.2.0.4

Viewed 1000+ times

You Asked

I'm trying to broadcast a message using dbms_aq.enqueue with a queue set to multiple consumers.

The consumers on the queue comes and goes, so building up a recipient_list through various SQL on the raw queue information is not an option.
I'm stuck, is there an easy way around this.

Here is the code snippet, what am I missing?

    procedure queue_aq(
                    p_data in dcn_rt
                    )
    is
        l_enqueue_options       dbms_aq.enqueue_options_t;
        l_message_properties    dbms_aq.message_properties_t;
        l_message_handle        raw(16);
    begin
        l_enqueue_options.visibility := dbms_aq.immediate;
        l_enqueue_options.delivery_mode := dbms_aq.buffered;
        l_message_properties.expiration := 240;

        dbms_aq.enqueue(
                    queue_name => 'rator.dcn_aq',
                    enqueue_options => l_enqueue_options,
                    message_properties => l_message_properties,
                    payload => p_data,
                    msgid => l_message_handle
                    );
    exception
        when ex_no_recipients then null;
        when others then
            begin
                debug('Exception in queue: ' || sqlcode || ' - ' || sqlerrm);
            end;
    end;


The usage is to keep caches in Java VM's in synch with the database. I'm using Database Change Notification trap the changes to specific tables, and then using AQ with multiple consumers to distributes table_name, action (insert/update/delete) and rowid on changed rows.

The type DCN_RT is as follows:
create type dcn_rt as object (
    table_name          varchar2(30),       -- Table affected
    action              varchar2(10),       -- Action performed (INSERT/UPDATE/DELETE)
    row_id              varchar2(30),       -- ROWID affected
    dcn_ts              timestamp,          -- Seen by DCN callback
    enq_ts              timestamp,          -- Queue to AQ
    deq_ts              timestamp           -- Dequeued from AQ
);
/

Where the timestamps are instrumentation information for later use.


and Chris said...

If you have a multiconsumer queue, a message remains on it until all subscribers have received the data. As you change the consumers, just add or remove the subscribers as needed!

That said, it sounds like you're mixing two separate things. With Database Change Notification you register your agents with the database. The change events already contain details about what changed. So I'm not sure what you need the AQ for...

See:

https://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm#JJDBC28815
https://docs.oracle.com/cd/B28359_01/win.111/b28375/featChange.htm

Is this answer out of date? If it is, please let us know via a Comment

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library