When we start a job via dbms_schedular, it creates a record in *_SCHEDULER_JOBS
Is there a way at the middle or end of a job. I write onto the record
Example:
Job_A spawns Procedure_B
And inside Procedure_B, I can write back to the record in *_scheduler_jobs in Job_A
As procedure_B is looping on a sequence of sub-task e.g. batch_id=1 to 10
and I want to write id=1 and id=10 into the entry for Job_A in *_SCHEDULER_JOBS
-Thanks for all the help.
Question is a bit vague on "I want to write id=1 and id=10 into the entry for Job_A in *_SCHEDULER_JOBS".
From within the procedure, you can use the SYS_CONTEXT('USERENV','BG_JOB_ID') to get the object id of the scheduler job, and look the owner / name up in ALL_OBJECTS. If the job is owned by the same user as the procedure or has been granted appropriate privileges, it can then call DBMS_SCHEDULER.SET_ATTRIBUTE to make changes to the job. Depending what attribute it changes, that will probably only kick in for the next run of the job.
BG_JOB_ID only works if the job is run from the scheduler, and not if someone is doing dbms_scheduler.run_job within their own session. Given multiple sessions could do this concurrently, you probably don't want them all trying to make changes to the job anyway.
Related
Env: Oracle 12c R2
Trying to understand what the best approach would be to set up an Oracle DBMS_SCHEDULER job that would be used to monitor a DBMS_ALERT trigger that checks when a specific column value changes within a table.
The thing is, this table column value change will sometimes occur on a frequent basis and sometimes it may only occur twice a day but I will need to monitor this column change via the DBMS_ALERT.
The trigger I have is as follows and I have a procedure called check_signal that checks for the signal that I wish to use within the DBMS_SCHEDULER job.
The goal that I am trying to achieve is that I am going to have the situation where I will need to run say, three jobs:
Job1
Job2
Job3
The thing is, the payload returned from Job1 is required and and passed as parameters into Job2 and again, the payload returned from Job2 is required and passed as parameters into Job3.
It is this wait/alert that I am trying to achieve through the use of DBMS_ALERTS.
create or replace trigger my_tab_upd after update of status on my_tab for each row
begin
dbms_alert.signal('mystatusalert', 'changed from '||:old.status||' to '||:new.status||'.');
end;
/
This will be used via a web-based application which is used by multiple users.
Just unsure on how to setup this scheduled job that will continuously check for the alert and then be used within the web app.
If there is a better means than DBMS_ALERT, then please let me know.
The general answer is simple, while polling for events every N seconds you get an average delay N/2 seconds and maximal delay of N seconds.
In context of DBMS_ALERT you should re-think this approach, as this will implement polling with wait on the event.
The periodically executed jobs make basically tho thinks:
DBMS_ALERT.REGISTER on an event name
wait with DBMS_ALERT.WAITONE
Assume that the DBMS_SCHEDULER jobs runs every 10 seconds and it is started in the phase with frequent signalling. So the first execution returns quickly after receiving an event.
The second execution falls in the quite period, so the job will wait hours to get an event.
I think this is not what you expect as
1) the waiting job will have an open session - what you want to avoid as follows from you other question
You may use timeout = 0 in the DBMS_ALERT.WAITONE, but this will return close to no events, except those fired accidentally between the REGISTER and WAITONE
2) if in the first 10 seconds two events are signalled, the second one will be lost as at the signaling time the subscribing job is not active and no registration exists.
I'm setting up a Quartz driven job in a Spring. The job needs a single argument which is the id of a database record that it can use to locate the data it needs to process.
The sequence is:
Job starts,
locates next available record id,
processes data.
Because the record id is unknown until the job starts, I cannot set it up when I create the job. I also need to account for restarts if things go bad. From reading Quartz doco it appears that if I store the record Id in the trigger's JobDataMap, then when the server restarts, the job will automatically restart with the same record Id it was original started with.
This is where things get tricky, I'm trying to figure out where and when to get the record Id so I can store it in the trigger's JobDataMap. I'm thinking I need to implement a TriggerListener and use it to set the record Id in the JobDataMap when the triggerFired() callback is called. This will involve a call to the database to get the record Id.
I'm not really sure if this approach is the correct one, or whether I'm barking up the wrong tree. Can someone with some quartz experience tell me if this is correct, or if there is a better way to configure a jobs arguments so that they can be dynamically set and a restart will preserve them?
Thanks
Derek
I learned (the hard way) that DDL statements cannot be executed in the non-transactional context of a logon trigger, and that the solution is a job. I want the job to be executed immediately and one single time and therefore set the next_date parameter to sysdate and the interval parameter to null.
Here is what I execute in the trigger:
dbms_job.submit(
job=>jobNumber,
what=>'someProcedure(someParameter);',
next_date=>sysdate,
interval=>null
);
This works quite good, but once the trigger has been fired (and the above command has been submitted) for the time, the audit log shows that the job keeps reappearing exactly every five seconds under the same user account it has been submitted under for the first time. The associated program is always something like ORACLE.EXE (J001), although it was of course a user session initiated from a client application.
Can anyone explain this to me please? I hoped to get a singular execution of the job and not an eternal recurrence. Thanks in advance!
I am creating a library system.
When a book is reserved, i want it to automatically change the status back to "Available" in 3 days if the reserved user does not borrow it.
I can create a trigger to fire when the status is changed to "Reserved" but I am lost on creating a job to happen in 3 days and change the status back to "Available"
Any comments, advises and guidance will be greatly appreciated :)
You should first create a procedure to update the column as you want, taking as an input parameter the book id (or whatever else as PK).
In your trigger, call the submit procedure of dbms_scheduler package and define the start date in 3 days time, without redundance, and to run your procedure defined earlier with the :new.bookid as input parameter.
Once the transaction has be commited later on, the job will be submitted. Else, in case of rollback of the transaction the job will be rolled back as well.
Nicolas.
what language are you coding in?
Generally for something like this I write a cron job which would run periodically (once a day before library hours?), do a query to see everything that's been reserved for more than 3 days, and set it back to available.
I use PHP and Oracle, with crontab executing the PHP scripts at scheduled times. My current logging/auditing solution involves simple log files. I'd like to save my cron execution logs to a database instead.
Right now I'm trying to design the process so that when a cron job starts I create a record in an CronExecution table. Then every time I want to log something for that cron I'll put a record in a CronEvent table which will have a foreign key to the CronExecution table.
I plan to log all events using a PRAGMA AUTONOMOUS pl/sql procedure. With this procedure I will be able to log events inside of other pl/sql procedures and also from my PHP code in a consistent manner.
To make it more robust, my plan is to have a fallback to log errors to a file in the event that the database log calls fail.
Has anybody else written something similar? What suggestions do you have based on your experience?
Yep, I've done this several times.
The CronExecution table is a good idea. However, I don't know that you really need to create the CronEvent table. Instead, just give yourself a "status" column and update that column.
You'll find that makes failing over to file much easier. As you build lots of these CronExecutions, you'll probably have less interest in CronEvents and more interest in the full status of the execution.
Wrap all of the update calls in stored procedures. You definitely have that correct.
Including a 'schedule' in your CronExecution will prove handy. It's very easy to have a lot of cron jobs and not be able to connect the dots on "how long did this take?" and "when is this supposed to run". Including a "next scheduled run" on completion of a job will make your life much easier.
You will want to read the documentation on DBMS_SCHEDULER.
It's a little bit of work to implement (what isn't?), but it will allow you to control scheduled and one-time jobs from within the database. That includes OS-level jobs.