Home » SQL & PL/SQL » SQL & PL/SQL » Asynchronous procedure calls (10.2.0.1, XP)
Asynchronous procedure calls [message #550929] Fri, 13 April 2012 11:00 Go to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Hi,

This is the requirement...

-- We get the data into a table directly from an external source.
-- Each time we get a record into the table, a procedure needs to be executed.
-- Sometimes while the procedure is being executed, there will be records inserted into the table.
-- So the procedure should be executed again without waiting for the previous execution.
-- The problem with DBMS_JOB is we need to specify start time & refresh interval which we don't want to specify.
-- SO as soon as we get a record into the table, procedure should start executing & the control should be returned back without waiting like Unix where we mention "&" so that jobs will be run in the background.
Re: Asynchronous procedure calls [message #550931 is a reply to message #550929] Fri, 13 April 2012 11:05 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3305
Registered: January 2010
Location: Connecticut, USA
Senior Member
rajivn786 wrote on Fri, 13 April 2012 12:00
Hi,

-- The problem with DBMS_JOB is we need to specify start time & refresh interval which we don't want to specify.


Why? DBMS_JOB.RUN runs job on demand.

SY.
Re: Asynchronous procedure calls [message #550932 is a reply to message #550929] Fri, 13 April 2012 11:06 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Quote:
-- The problem with DBMS_JOB is we need to specify start time & refresh interval which we don't want to specify.


No, start time is SYSDATE and refresh is NULL.
You trigger the job from a trigger on insert into the table.

Regards
Michel
Re: Asynchronous procedure calls [message #550933 is a reply to message #550931] Fri, 13 April 2012 11:08 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
when all else fails Read The Fine Manual

http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_job.htm#i1000972

EXECUTE DBMS_JOB.RUN(14144);

but I suspect that you'll now uncover other difficulties with this flawed "design".

[Updated on: Fri, 13 April 2012 11:10]

Report message to a moderator

Re: Asynchronous procedure calls [message #550934 is a reply to message #550933] Fri, 13 April 2012 11:16 Go to previous messageGo to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Just wanted to know...If we trigger a job from a trigger on insert into the table, it does not wait for the previous job to complete..& it can span as many processes like in Java???
Re: Asynchronous procedure calls [message #550935 is a reply to message #550934] Fri, 13 April 2012 11:26 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
when does COMMIT get issued so other session can see new row (since can NOT issue COMMIT from inside trigger)?
Re: Asynchronous procedure calls [message #550936 is a reply to message #550934] Fri, 13 April 2012 11:41 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
rajivn786 wrote on Fri, 13 April 2012 18:16
Just wanted to know...If we trigger a job from a trigger on insert into the table, it does not wait for the previous job to complete..& it can span as many processes like in Java???


The job goes as soon as the transaction is commited (actually a couple of seconds later) which means when the row is really inserted, before it is not, and it is asynchroneous.

Regards
Michel
Re: Asynchronous procedure calls [message #551023 is a reply to message #550936] Sat, 14 April 2012 22:26 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Off hand, it sounds like a job for ADVANCED QUEUES Here is a quote from the manuals:

Quote:
Advanced Queuing provides the message management functionality and asynchronous communication needed for application integration.


I have some moderate experience with asynchronous applications using Oracle features. Enough to know that done badly you can easily get in trouble. It sounds to me like you have not fully thought out the problem and how you want it to work. This is not meant as an insult, just that there are lots of details involved. For example, do you need rows inserted in the table to be guaranteed to be processed in a specific order (FIFO or LIFO or etc.)? Are there performance requirements? What are the ramifications of delays of the asynchronous solution you choose?

Answers to these questions and others will help you see what asynchronous solutions might work for you. I would stay away from any trigger based solution however. Especially if you consider that triggers can do implicit rollbacks and thus execute their trigger code multiple times before they get it right, which could lead to multiple executions of your external procedure for the same row. How would you know if this happened and how will you deal with the consequences of it?

Good luck.

[Updated on: Sat, 14 April 2012 22:28]

Report message to a moderator

Re: Asynchronous procedure calls [message #551240 is a reply to message #551023] Mon, 16 April 2012 10:03 Go to previous messageGo to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Yes...I was thinking about Advanced Queuing the other day before posting the message..But looks like a complex concept to understand..& also couldn't find proper examples..As far as I know, I guess we can filter it out based on the time stamp whether it's FIFO or LIFO..SO I hope that wouldn't be a problem here..It's more like as soon as you get the row in the table u process it without any delay..as it's patient related data ..Can u provide me a good example based on my scenario using AQ..
Re: Asynchronous procedure calls [message #551243 is a reply to message #551240] Mon, 16 April 2012 10:09 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
AQ means you have someone that dequeues the messages.

Regards
Michel
Re: Asynchronous procedure calls [message #551244 is a reply to message #551240] Mon, 16 April 2012 10:50 Go to previous messageGo to next message
John Watson
Messages: 8988
Registered: January 2010
Location: Global Village
Senior Member
Here's a simple example of setting an AQ. I developed it when I was setting up a system to control event driven jobs, which are what you want: you should be using the Scheduler for this sort of thing, not dbms_job.

Run steps 1 through 6 once, then repeat 7 and 8 a few times and you'll see what is going on. If you find this useful and build something based on queues, I hope you will feed back with the full details. It is an interesting area, where more research is needed.
Event driven jobs:

1.	Create an abstract data type to define the events:

create type incoming_t as object(event_type number);

2	Create a queue table to store queues that use this object type:

execute dbms_aqadm.create_queue_table(queue_table=>'incoming_qt',-
queue_payload_type=>'incoming_t',multiple_consumers=>true);

3.	Create a queue in the table:

exec dbms_aqadm.create_queue(-
queue_name=>'incoming_q',queue_table=>'incoming_qt');

4.	Create a de-queuing agent, and add it to the queue:

exec dbms_aqadm.create_aq_agent('inc_agent');
exec dbms_aqadm.add_subscriber(-
'incoming_q',sys.aq$_agent('inc_agent',null,null));

5.	Start the queue:

exec dbms_aqadm.start_queue(queue_name=>'incoming_q');

6.	Create a job that will monitor the queue and run when a certain event is enqueued:

exec dbms_scheduler.create_job(-
job_name => 'load_data',-
job_type => 'stored_procedure',-
job_action => 'read_file',-
start_date => systimestamp,-
queue_spec => 'incoming_q,inc_agent',-
event_condition => 'tab.user_data.event_type=1',-
enabled => true);

7.	Include code in the event generating application(s) to enqueue messages:

declare 
enqueue_options dbms_aq.enqueue_options_t;
message_properties dbms_aq.message_properties_t;
msgid raw(16);
payload incoming_t;
begin
payload := incoming_t(1);
dbms_aq.enqueue(queue_name => 'incoming_q',
enqueue_options => enqueue_options,
message_properties => message_properties,
payload => payload,
msgid => msgid);
commit;
end;

8.	Prove that the job did run:

select  JOB_NAME , log_Date from user_SCHEDULER_JOB_RUN_DETAILS
where job_name like 'LOAD%';




[update: I've just noticed that you are running with 10g. So you don't have event driven jobs. Well, you'll have to re-write steps 6 and 8.]

[Updated on: Mon, 16 April 2012 10:53]

Report message to a moderator

Re: Asynchronous procedure calls [message #551246 is a reply to message #551244] Mon, 16 April 2012 11:26 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Quote:
you should be using the Scheduler for this sort of thing, not dbms_job.


You mean for your AQ example? Otherwise I disagree for the most important reason that dbms_scheduler is not part of your transaction, this means that if (for OP's case) you insert a row and then roll back the job will nevertheless executes.

I will not use AQ for this as it is very very simple to call dbms_job passing a procedure to execute with the rowid of the inserted row and many improvement can be done to piggyback several rows as Log Miner does for commit and then you have not a trigger for each row but for each statement and even not a job for each statement.

Regards
Michel
Re: Asynchronous procedure calls [message #551248 is a reply to message #551244] Mon, 16 April 2012 11:55 Go to previous messageGo to next message
Kevin Meade
Messages: 2103
Registered: December 1999
Location: Connecticut USA
Senior Member
Cool Stuff Man!

This is why you need first to really understand what it is you are trying to achieve. Your answers to the requirements, limitations, transaction consistency, and error handling questions MUST BE DONE before you can choose wisely, a satisfactory solution.

Consider that there are at last count, at least four ways to achieve this kind of functionality:

1) Home Grown Sentinal Method (trigger,table,agent)
2) Alerts (9i) using DBMS_ALERT
3) Change Notification using DBMS_CHANGE_NOTIFICATION
4) Advanced Queueing using DBMS_AQ


Each of the above clearly has advantages and detractors, and their behaviors are also different as well but you could create a solution for yourself using any of them. The differences and quirks of each however, will matter. For exampe:

If you did not know that DBMS_CHANGE_NOTIFICATION has limits on the number of ROWIDS it can return before it just says "LOTS" then you would not know to factor that into your solution design.

If you did not know that DBMS_ALERT is a transaction consistent event and will only propogate an alert upon commit thus means it only alerts on successful events, then you would not know that you will never get notification on failures and rollbacks and ATTEMPTS to perform the operation. For most people this is the desired behavior but for some it is not.

And so on...

So ask you self things like:

How would it matter if I lost notification of events on a row or two?
How would it matter if I lost notification of events on a lot of rows?
How would it matter if I processed the notification event on the same row more than once?
How would it matter if there was a delay in processing an event notification of minutes or even days?
How would it matter if notification events were processed in an unknown order?


You will see that your design and choice of tools to do the job will be determined by understanding the answerws to these questions and how the different tools you might choose from (1-4 above) would address each of them. Of course for that you have lots of reading to do.

Keep in mind that the three Oracle alternatives were designed for specific purposes. The further away you get from the basic reason each was created; which is to say, the more you try to bend the tool to your will rather than using the tool the way it wants to be used, the more likely it is you will have trouble.

Also keep in mind that not using one of the Oracle supplied tools means writing a lot of your own code and potentially create more error prone and less performant solutions. For the most part, Oracle features are well tested and made as optimally performant as possible. I for one am constantly amazed at how many application teams are keen to duplicate a feature that Oracle already provides.

http://www.oracle-base.com/articles/10g/dbms_change_notification_10gR2.php

http://docs.oracle.com/cd/B10500_01/appdev.920/a96587/qintro.htm

http://www.dbforums.com/oracle/947351-dbms_alert-usage.html

Good luck, Kevin.
Re: Asynchronous procedure calls [message #551249 is a reply to message #550932] Mon, 16 April 2012 11:59 Go to previous messageGo to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Michael,

Still to test on AQ..But before that I just wanted to know whether
the following from my manager is true or not...

:"If you specify sysdate then it may not execute as when it checks the queue the time may be past and with refresh null it may not execute at all. That is something we need to test and read about if entry with sysdate will cause the job to be executed right away."

So do you agree with this..
Re: Asynchronous procedure calls [message #551266 is a reply to message #551249] Mon, 16 April 2012 13:51 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
It is easy to verify it:
SQL> create table t (dt date);

Table created.

SQL> var jno number;
SQL> declare jno pls_integer; 
  2  begin
  3    dbms_job.submit(:jno, 'begin insert into t values(sysdate); commit; end;');
  4    commit;
  5  end;
  6  /

PL/SQL procedure successfully completed.

SQL> print jno
       JNO
----------
        52

SQL> select * from dba_jobs where job=52;

no rows selected

SQL> select * from t;
DT
-------------------
16/04/2012 20:50:05

1 row selected.

If it does not work then check Metalink note "Jobs Not Executing Automatically [ID 313102.1]".

Regards
Michel
Re: Asynchronous procedure calls [message #551275 is a reply to message #551266] Mon, 16 April 2012 15:18 Go to previous messageGo to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Michael,

I am having trouble with the code while inserting into table "x" with the job number .

CREATE OR REPLACE TRIGGER orders_after_insert
    AFTER INSERT
        ON x
        FOR EACH ROW

DECLARE          
 v_mr varchar2(100) := '';       
 v_sql varchar2(1000) := ''; 
 jno pls_integer ; 

BEGIN
       SELECT :new.mrn INTO v_mrn    FROM DUAL;

   V_SQL := 'BEGIN DBMS_JOB.SUBMIT ( ' || jno || ' , '' begin x_prc (' || v_mr || '); end;'' ) ; END;';
     dbms_output.put_line (V_SQL);  

  EXECUTE IMMEDIATE v_sql ;    
     
    END;


Just wanted to know how to assign/pass job number...
If I pass this it doesn't take any value into the job number..When I am using bind variables it says "variables not bound"..
Re: Asynchronous procedure calls [message #551283 is a reply to message #551275] Mon, 16 April 2012 17:12 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
http://www.orafaq.com/node/871
Re: Asynchronous procedure calls [message #551301 is a reply to message #551275] Tue, 17 April 2012 01:03 Go to previous messageGo to next message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
You don't need to use EXECUTE IMMEDIATE to call a procedure.
And you don't to select from dual to assign a value.

CREATE OR REPLACE TRIGGER orders_after_insert
AFTER INSERT ON x FOR EACH ROW
DECLARE          
  jno pls_integer; 
BEGIN
  DBMS_JOB.SUBMIT (jno, 'x_prc (' || :new.mrn || ');');
END;
/


Regards
Michel
Re: Asynchronous procedure calls [message #551353 is a reply to message #551301] Tue, 17 April 2012 10:15 Go to previous messageGo to next message
rajivn786
Messages: 161
Registered: January 2010
Senior Member
Michael,

It works...Inserted 10 records into table x & looked out user_jobs table..I can see 10 jobs in that table with same next_date & next_sec..Just wanted to confirm that..does it mean all 10 jobs ran at the same time without waiting for output from the previous job..

Thanks..
Re: Asynchronous procedure calls [message #551354 is a reply to message #551353] Tue, 17 April 2012 10:18 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
what SQL did you run?
what did you see?
Re: Asynchronous procedure calls [message #551355 is a reply to message #551353] Tue, 17 April 2012 10:22 Go to previous message
Michel Cadot
Messages: 68767
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Quote:
does it mean all 10 jobs ran at the same time without waiting for output from the previous job..


Running jobs are independent sessions and run in parallel up to the limit given by job_queue_processes.

Regards
Michel

[Updated on: Tue, 17 April 2012 10:22]

Report message to a moderator

Previous Topic: ORA-24248: XML DB extensible security not installed
Next Topic: Syntax for Optional 'ALL' Parameter in Oracle SQL
Goto Forum:
  


Current Time: Fri Aug 22 18:25:56 CDT 2025