Asynchronous procedure calls [message #550929] |
Fri, 13 April 2012 11:00  |
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   |
Solomon Yakobson
Messages: 3305 Registered: January 2010 Location: Connecticut, USA
|
Senior Member |
|
|
rajivn786 wrote on Fri, 13 April 2012 12:00Hi,
-- 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 #551023 is a reply to message #550936] |
Sat, 14 April 2012 22:26   |
 |
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   |
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 #551244 is a reply to message #551240] |
Mon, 16 April 2012 10:50   |
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 #551248 is a reply to message #551244] |
Mon, 16 April 2012 11:55   |
 |
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   |
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 #551275 is a reply to message #551266] |
Mon, 16 April 2012 15:18   |
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 #551353 is a reply to message #551301] |
Tue, 17 April 2012 10:15   |
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 #551355 is a reply to message #551353] |
Tue, 17 April 2012 10:22  |
 |
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
|
|
|