I am using following query to enable the oracle job:
exec dbms_scheduler.disable('23');
where '23' is my Job id. But this seems to be not working for id. I read that, job name should be given in place of '23'. But my job does not have name. It has only Id.
So how to enable it using job Id? any other command to execute?
older DBMS_JOBS had IDs, not scheduler ones. ie you may want this(if your seeing your job in DBA_JOBS view):
begin
dbms_job.broken(23, true);
commit;
end;
/
Related
I have a .net web service that makes some dynamically generated sql calls against ORACLE and they are performing bad in production. The DBAs keep asking for the sql ids to tune the query. They can use the OEM tool to find the slow performing query and get the sql id. But I was wondering if there is a way to know the sql id and log it so that I can retrieve it and give it to the DBAs for tuning.
Is this something that can be achieved in .net ?
Query the V$SQL dynamic view to get the SQL ID;
More on the V$SQL:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/dynviews_2113.htm#REFRN30246
The following package dbms_application_info is very useful to instrument your queries.
Prior to running the processing logic from app layer, set the module/action, to identify your module.
DBMS_APPLICATION_INFO.set_module(module_name => 'add_order',
action_name => 'processing orders');
After that, set the client_info with a marker that indicates what processing is going on prior to running the sql.
Eg:
exec dbms_application_info.set_client_info('starting load from staging');
--Run the query
insert into dest_table select * from staging;
update dest_table set last_updated=sysdate;
exec dbms_application_info.set_client_info('updated the last_updated column');
delete from dest_table where order_value<0;
exec dbms_application_info.set_client_info('deleted -ve orders');
When this happens we can have a look at v$session/v$sql to see where the processing is currently taking place
SELECT sid,
serial#,
username,
osuser,
module,
action,
client_info
FROM v$session
WHERE module='add_order'
SELECT *
FROM v$sql
WHERE module='add_order'
have a look at the link
https://oracle-base.com/articles/8i/dbms_application_info
If the application can capture sufficient information to identify the session in v$session, you can query it from another session to grab the value of sql_id, or else query the v$sql_monitor view if you are licensed (requires Enterprise Edition and the Diagnostics and Tuning option). Use dbms_application_info to tag activity for better tracking.
Also you can configure database services if you haven't already, so that applications connect to a specific service rather than a generic one, and this will appear in v$session.service_name and be reported in OEM etc.
If it's practical to capture the session details from the same session immediately after the poorly-performing SQL statement completes (which it may not be, if the connection times out for example), you might try querying the prev_ details from v$session:
select s.prev_sql_id
, s.prev_child_number
, s.prev_exec_start
, s.prev_exec_id
, p.sql_text as prev_sql
, p.plan_hash_value as prev_plan
from v$session s
left join v$sql p on p.sql_id = s.prev_sql_id and p.child_number = s.prev_child_number
where s.audsid = sys_context('userenv', 'sessionid')
I would like to find the proper documentation to confirm my thought about a SQL Server job I recently wrote. My fear is that data could be inconsistent for few milliseconds (timing between the start of the job execution and its end).
Let's say the job is setup to run every 30 minutes. It will only have one step with the following SQL statement:
DELETE FROM myTable
INSERT INTO myTable
SELECT *
FROM myTableTemp
Could it happens that a SELECT query would be executed exactly in between the DELETE statement and the INSERT statement and thus returning empty results?
And what if I would have created 2 steps in my job, one for the DELETE query and another for the INSERT INTO? Is the atomicity is protected by SQL Server between several steps of one job?
Thanks for your help on this one
No there is no automatic atomic handling of jobs, whether they are multiple statements or steps.
Use this:
begin transaction
delete...
insert....
... anything else you need to be atomic
commit work
I defined a job to run from Tuesday to Sundays every 5 min. from 9:00 am to 22:00 pm
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'GET_INVOICES_JOB',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN LOPES.GET_INVOICES; END;',
repeat_interval =>'FREQ=MINUTELY; INTERVAL=5; BYHOUR=9,22; BYDAY=TUE,WED,THU,FRI,SAT,SUN',
enabled => TRUE,
comments => 'GET_INVOICES');
END;
/
But the job does not run cheking
SELECT *
FROM USER_SCHEDULER_JOB_RUN_DETAILS
ORDER BY LOG_DATE DESC
Checking the Job it seems to be OK:
and running the job manually it execute the procedure but only once not every 5 minutes
This is one of the most common Scheduler questions asked.
Here we list some of the common problems and their solutions.
1) job_queue_processes may be too low (this is the most common problem)
The value of job_queue_processes limits the total number of dbms_scheduler
and dbms_job jobs that can be running at a given time.
To check whether this is the case check the current value of
job_queue_processes with
SQL> select value from v$parameter where name='job_queue_processes';
Then check the number of running jobs
SQL> select count() from dba_scheduler_running_jobs;
SQL> select count() from dba_jobs_running;
If this is the problem you can increase the parameter using
SQL> alter system set job_queue_processes=1000;
2) max_job_slave_processes may be too low
If this parameter is not NULL then it limits how many dbms_scheduler jobs can
be running at a time. To check whether this is the problem, check the current
value using
SQL> select value from dba_scheduler_global_attribute
where attribute_name='MAX_JOB_SLAVE_PROCESSES';
Then check the number of running jobs
SQL> select count(*) from dba_scheduler_running_jobs;
If this is the problem you can increase the number or just NULL it out using
SQL> exec dbms_scheduler.set_scheduler_attribute('max_job_slave_processes',null)
3) sessions may be too low
This parameter limits the number of sessions at any time. Every Scheduler job
requires 2 sessions. To check whether this is the problem, check the current
valule using
SQL> select value from v$parameter where name='sessions';
Then check the current number of sessions using
SQL> select count(*) from v$session ;
If the numbers are too close you can increase the maximum using
SQL> alter system set job_queue_processes=200;
4) Have you recently applied a timezone update patch or upgraded the database
to a version with newer timezone information ? If you skipped any steps when
updating the timezone information, jobs may not run. To check whether this
is the case try doing
SQL> select * from sys.scheduler$_job;
and
SQL> select * from sys.scheduler$_window;
and make sure they finish without errors.
If it throws a timezone warning, reapply the upgrade or
timezone patch making sure to follow all the steps.
5) Is the database running in restricted mode ?
If the database is running in restricted mode then no jobs will run (unless
you are using 11g and use the ALLOW_RUNS_IN_RESTRICTED_MODE attribute).
To check this use
SQL> select logins from v$instance ;
If logins is restricted you can disable the restricted mode using
SQL> ALTER SYSTEM DISABLE RESTRICTED SESSION;
6) Is the job scheduled to run on an instance which is down ?
You can check this by seeing whether instance_id is set for the job (check the dba_scheduler_jobs view), and if so you should check whether that instance is up.
7) Is the job scheduled to run on a service which has not been started on any instances ?
You can check this by checking what job_class a job points to and then checking whether that class points to a service. If it does, make sure the service has been started on at least one running instance. You can start a service on an instance using dbms_service.start_service.
8) Is the Resource Manager in effect with a restrictive resource plan ?
If a restrictive resource plan is in effect, scheduler jobs may not have sufficient resources allocated so they may not run. You can check what resource plan is in effect by doing
SQL> select name from V$RSRC_PLAN ;
If no plan is in effect or the plan in effect is INTERNAL_PLAN then the resource manager is not in effect. If the resource manager is in effect you can disable it by doing
SQL>alter system set resource_manager_plan = '';
9) Has the Scheduler been disabled ? This is not a supported action
but it is possible that someone has done it anyway. To check this do
SQL> select value from dba_scheduler_global_attribute where attribute_name='SCHEDULER_DISABLED'
If this query returns TRUE then you can fix this using
SQL> exec dbms_scheduler.set_scheduler_attribute('scheduler_disabled','false');
Reasons why jobs may run late
1) The first thing to check is the timezone that the job is scheduled with
SQL> select owner, job_name, next_run_date from dba_scheduler_jobs ;
If the jobs are in the wrong timezone they may not run at the expected
time. If the next_run_date is using an absolute timezone offset (like
+08:00) instead of a named timezone (like US/PACIFIC) then the jobs may not
run as expected if daylight savings is in effect - they may run an hour
early or late.
2) It may be that at the time the job was scheduled to run, one of the several
limits above may have been temporarily reached causing the job to be delayed.
Check if the limits above are high enough and if possible check them during
the time that the job is being delayed.
3) One possible reason that one of the above limits may be hit is that a
maintenance window may have come into effect. Maintenance windows are Oracle
Scheduler windows that belong to the window group named
MAINTENANCE_WINDOW_GROUP. During a scheduled maintenance window, several
maintenance tasks are run using jobs. This may cause one of the limits listed
above to be hit and user jobs to be delayed. See the admin guide for more info
about this (chapter 24).
To get a list of maintenance windows use
SQL> select * from dba_scheduler_wingroup_members;
To see when the windows run use
SQL> select * from dba_scheduler_windows;
To fix this you can either increase the limits or reschedule the maintenance
windows to run at more convenient times.
Diagnosing other Problems
If none of this works, here are some further steps you can take to try to
figure out what is going on.
1) Check whether there are any errors in the alert log. If the database is
having trouble allocating memory or has run out of disk space or any other
catastrophic errors have occurred, you should resolve those first. You can
find the location of the alert log by using
SQL> select value from v$parameter where name = 'background_dump_dest';
The alert log will be in this directory with a name starting with "alert".
2) Check whether if a job coordinator trace file and if it does, check if it
contains any errors. If this exists, it will be located in the
'background_dump_dest' directory which you can find as above and will look
something like SID-cjq0_nnnn.trc . If there are any errors here they may
hint at why jobs are not running.
3) If either of the above indicates that the SYSAUX tablespace (where the scheduler stores its logging tables) is full, you can use the dbms_scheduler.purge_log procedure to clear out old log entries.
4) See if there is a window currently open. If there is, you can try closing it to see if that helps .
SQL> select * from DBA_SCHEDULER_GLOBAL_ATTRIBUTE where
attribute_name='CURRENT_OPEN_WINDOW';
SQL> exec DBMS_SCHEDULER.close_window ('WEEKNIGHT_WINDOW');
5)try running a simple run-once job and see if it runs
SQL>begin
dbms_scheduler.create_job (
job_name => 'test_job',
job_type => 'plsql_block',
job_action => 'null;',
enabled => true);
end;
/
SQL> -- wait a while
SQL> select * from user_scheduler_job_run_details where job_name='TEST_JOB';
6) If a simple run-once job doesn't run, you can try restarting the scheduler as follows.
SQL> exec dbms_scheduler.set_scheduler_attribute('SCHEDULER_DISABLED', 'TRUE');
SQL> alter system set job_queue_processes=0;
SQL> exec dbms_ijob.set_enabled(FALSE);
SQL>
SQL> alter system flush shared_pool;
SQL> alter system flush shared_pool;
SQL>
SQL> exec dbms_ijob.set_enabled(TRUE);
SQL> alter system set job_queue_processes=99;
SQL> exec dbms_scheduler.set_scheduler_attribute('SCHEDULER_DISABLED', 'FALSE');
In a Multitenant environment the container also has to have the right value for the job_queue_processes.
I've been trying to get SQL Developer to run a query automatically on a regular basis (on the sample HR database). Based on my research, I've determined that the best alternative for me would be to use the Job Wizard & PL/SQL (where it calls DBMS_SCHEDULER?).
I created a 'Schedule' that repeats every 5 minutes called: every_5mins
Here is what I have in the 'Job Details' section thus far:
Job Name: Select_Employees
Job Class: SYS.DEFAULT_JOB_CLASS
Type of Job: PL/SQL block
When to Execute Job: Schedule
Schedule: SYSTEM.EVERY_5MINS
PL/SQL
CREATE OR REPLACE
PROCEDURE get_emp_rs (p_deptno IN HR.FIRST_NAME,
p_recordset OUT SYS_REFCURSOR) AS
BEGIN
OPEN p_recordset FOR
SELECT FIRST_NAME,
LAST_NAME
FROM
HR.EMPLOYEES
WHERE FIRST_NAME=p_recordset
END;
/
it returns an error:
"Encountered the symbol "/" when expecting one of the following: (begin case declare)..." and the rest is cut off the screen
Am I on the right track? What is the proper way to write it so the query is run every 5 mins? I have never used Oracle SQL Developer before.
Thanks in advance.
I have a new error: line 1, column 750 PLS-00103: Encountered the symbol "CREATE"
The PL/SQL payload is the code we want our job to execute. So it seems you are trying to schedule the creation of stored procedure every five minutes. The scheduler is expecting an executable PL/SQL call, not DDL.
So what you need to to is create the stored procedure first, then fire up the Job wizard. The PL/SQL block should be something like this:
declare
rc sys_refcursor;
begin
get_emp_rs ('MAYZIE', rc);
end;
This points us to the underlying problem with your scenario: jobs run in the background. There's no way for a job to accept user input or display output. So while your job will run every five minutes you'll never see the result set. You need a procedure which writes results somewhere (a table, a file) which can be read and displayed by some other program.
I have created a trigger and I want to stop the trigger from executing its code for some time. Is there any function available in oracle for this.
Being more specific:-
I have to perform an action when a PO is created in oracle apps.
I need to find requisition number for this po which I will get by joining distributions and lines table. But when trigger is fired there wont be any data in lines and distribution table.
alter trigger <trigger_name> disable;
then to enable
alter trigger <trigger_name> enable;
You cannot delay your trigger, it will fire as soon as you perform the event on the table.
There is no native database way to delay the trigger for some specified period of time.
In general you can enable or disable trigger using,
ALTER TRIGGER trigger_name ENABLE/DISABLE;
You can write this code in a stored procedure and then get it executed using some out-of-the-database program, e.g. PHP, JAVA, SHELL etc. (depending on your architecture) that supports time driven execution
DBMS_LOCK.SLEEP might to the trick:
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_lock.htm#ARPLS66781
You can easily delay an action by creating a job.
For example, your trigger may call DBMS_JOB.submit to create a job to run at a particular time (e.g. 10 minutes after the current time). The job needs to be created with the name of a procedure that needs to be run. For example, you might create a procedure that takes a record ID as a parameter.
The nice thing about DBMS_JOB is that it is transactional - so if your triggering statement is rolled back, the job will also be rolled back.
The downside is that the job will never start until after the statement that created it is committed.