I needed to create a one-click import with datapump script on Windows operating system, and for this I needed to create a database directory mapped on the current directory where the dumps are.
So I wrote an sql file:
create_directory.sql
CREATE OR REPLACE DIRECTORY DATAPUMP AS '&&1'
/
exit
/
And import_one_click.bat file looks like this:
sqlplus / as sysdba @create_directory.sql %CD%
impdp '/ as sysdba' directory=DATAPUMP dumpfile=export_andrei.dmp logfile=import_andrei.log schemas='ANDREI'
Thursday, 18 November 2010
Wednesday, 3 November 2010
how to fix a shared server issue?
This is more of a question for you guys.
In the alert log i have this:
Errors in file /oradb/app/oracle/admin/test/bdump/test_s003_123472.trc:
ORA-00600: internal error code, arguments: [ksudel1], [], [], [], [], [], [], []
ORA-00600: internal error code, arguments: [unable to load XDB library], [], [], [], [], [], [], []
Wed Nov 3 15:35:36 2010
found dead shared server 'S000', pid = (10, 2)
found dead shared server 'S001', pid = (24, 3)
found dead shared server 'S002', pid = (28, 1)
found dead shared server 'S003', pid = (29, 1)
And of course lots of trace files with test_s****.trc
Actually the solution I adopted is to make all connection on this database DEDICATED. So I changed everywhere SERVER=DEDICATED. And since then I had no error coming.
Do you have any ideas?
In the alert log i have this:
Errors in file /oradb/app/oracle/admin/test/bdump/test_s003_123472.trc:
ORA-00600: internal error code, arguments: [ksudel1], [], [], [], [], [], [], []
ORA-00600: internal error code, arguments: [unable to load XDB library], [], [], [], [], [], [], []
Wed Nov 3 15:35:36 2010
found dead shared server 'S000', pid = (10, 2)
found dead shared server 'S001', pid = (24, 3)
found dead shared server 'S002', pid = (28, 1)
found dead shared server 'S003', pid = (29, 1)
And of course lots of trace files with test_s****.trc
Actually the solution I adopted is to make all connection on this database DEDICATED. So I changed everywhere SERVER=DEDICATED. And since then I had no error coming.
Do you have any ideas?
Thursday, 28 October 2010
how to create pl/sql procedure to send mails
This is an example of a procedure that sends an email from an Oracle10g database:
CREATE OR REPLACE PROCEDURE p_send_mail (
sender IN VARCHAR2,
recipient IN VARCHAR2,
carbon_copies IN VARCHAR2 DEFAULT NULL ,
mail_subject IN VARCHAR2,
mail_body IN VARCHAR2
)
AS
conntype UTL_SMTP.connection;
mailsrvr VARCHAR2 (50) := 'mail_server_name_or_ip';
svrport VARCHAR2 (3) := 25;
svrdate VARCHAR2 (255) := TO_CHAR (SYSDATE, 'dd Mon yy hh24:mi:ss');
msghdr VARCHAR2 (2000) := NULL;
linefeed VARCHAR (2) := CHR (13) || CHR (10);
msgbody VARCHAR2 (8000);
activation_link VARCHAR2 (100);
BEGIN
conntype := UTL_SMTP.open_connection (mailsrvr, svrport);
msghdr :=
'Date: '
|| svrdate
|| linefeed
|| 'From: <'
|| sender
|| '>'
|| linefeed
|| 'Subject: '
|| mail_subject
|| linefeed
|| 'To: '
|| recipient
|| linefeed
|| ''
|| linefeed;
msgbody := msghdr || mail_body;
UTL_SMTP.helo (conntype, mailsrvr);
UTL_SMTP.mail (conntype, sender);
UTL_SMTP.rcpt (conntype, recipient);
UTL_SMTP.DATA (conntype, msgbody);
UTL_SMTP.quit (conntype);
END;
/
On this post you may find this procedure, an example on how to use this procedure and a solution to an error that he gets.
http://kr.forums.oracle.com/forums/thread.jspa?threadID=650243
Use it well.
CREATE OR REPLACE PROCEDURE p_send_mail (
sender IN VARCHAR2,
recipient IN VARCHAR2,
carbon_copies IN VARCHAR2 DEFAULT NULL ,
mail_subject IN VARCHAR2,
mail_body IN VARCHAR2
)
AS
conntype UTL_SMTP.connection;
mailsrvr VARCHAR2 (50) := 'mail_server_name_or_ip';
svrport VARCHAR2 (3) := 25;
svrdate VARCHAR2 (255) := TO_CHAR (SYSDATE, 'dd Mon yy hh24:mi:ss');
msghdr VARCHAR2 (2000) := NULL;
linefeed VARCHAR (2) := CHR (13) || CHR (10);
msgbody VARCHAR2 (8000);
activation_link VARCHAR2 (100);
BEGIN
conntype := UTL_SMTP.open_connection (mailsrvr, svrport);
msghdr :=
'Date: '
|| svrdate
|| linefeed
|| 'From: <'
|| sender
|| '>'
|| linefeed
|| 'Subject: '
|| mail_subject
|| linefeed
|| 'To: '
|| recipient
|| linefeed
|| ''
|| linefeed;
msgbody := msghdr || mail_body;
UTL_SMTP.helo (conntype, mailsrvr);
UTL_SMTP.mail (conntype, sender);
UTL_SMTP.rcpt (conntype, recipient);
UTL_SMTP.DATA (conntype, msgbody);
UTL_SMTP.quit (conntype);
END;
/
On this post you may find this procedure, an example on how to use this procedure and a solution to an error that he gets.
http://kr.forums.oracle.com/forums/thread.jspa?threadID=650243
Use it well.
how to gather statistics for all the tables
Gathering statistics for schemas, tables , indexes is a very important part of database maintaining tasks. Without statistics a growing database can have really big performance issues.
Here is a procedure that gathers statistics for every table except system ones for Oracle 10g
create or replace procedure analyze_tables
is
err_msg varchar2(200);
v_table varchar2(100);
v_owner varchar2(100);
v_sql varchar2(800);
cursor c_tabela is
select TABLE_NAME , owner
from dba_tables
where owner not in ('CTXSYS','SYS','SYSTEM','WMSYS','OUTLN','XDB','OWNER','DBSNMP','DMSYS','EXFSYS','SYSMAN','TSMSYS')
;
begin
open c_tabela;
fetch c_tabela into v_table,v_owner;
while c_tabela%found loop
v_sql:= 'begin DBMS_STATS.gather_table_stats ('''||v_owner||''','''||v_table||''',ESTIMATE_PERCENT=>50,METHOD_OPT=>''for all indexed columns size auto'', degree => 4, CASCADE=>True); end;';
execute immediate v_sql;
fetch c_tabela into v_table,v_owner;
end loop;
exception
when others then
err_msg := TO_CHAR(SQLCODE) || ':' || SQLERRM;
insert into log_rebuid (data, mesg_err) values (sysdate, 'SCHEMA '||err_msg );
end analyze_tables;
It is good to see on a production system a weekly job that gathers statistics, either fort tables, or schemas. Another interesting procedure is this one:
create or replace procedure rebuild_index (v_index in varchar2)
is
err_msg varchar2(200);
begin
execute immediate 'alter index '||v_index||' rebuild';
exception
when others then
err_msg := TO_CHAR(SQLCODE) || ':' || SQLERRM;
insert into log_rebuid (data, mesg_err) values (sysdate, 'INDEX '||err_msg );
end ;
It rebuilds the index on a table. Be careful because on a 24/7 database, it puts a lock on a table until the index is rebuilt. If it's a big index then you might have some locks on the database.
Here is a procedure that gathers statistics for every table except system ones for Oracle 10g
create or replace procedure analyze_tables
is
err_msg varchar2(200);
v_table varchar2(100);
v_owner varchar2(100);
v_sql varchar2(800);
cursor c_tabela is
select TABLE_NAME , owner
from dba_tables
where owner not in ('CTXSYS','SYS','SYSTEM','WMSYS','OUTLN','XDB','OWNER','DBSNMP','DMSYS','EXFSYS','SYSMAN','TSMSYS')
;
begin
open c_tabela;
fetch c_tabela into v_table,v_owner;
while c_tabela%found loop
v_sql:= 'begin DBMS_STATS.gather_table_stats ('''||v_owner||''','''||v_table||''',ESTIMATE_PERCENT=>50,METHOD_OPT=>''for all indexed columns size auto'', degree => 4, CASCADE=>True); end;';
execute immediate v_sql;
fetch c_tabela into v_table,v_owner;
end loop;
exception
when others then
err_msg := TO_CHAR(SQLCODE) || ':' || SQLERRM;
insert into log_rebuid (data, mesg_err) values (sysdate, 'SCHEMA '||err_msg );
end analyze_tables;
It is good to see on a production system a weekly job that gathers statistics, either fort tables, or schemas. Another interesting procedure is this one:
create or replace procedure rebuild_index (v_index in varchar2)
is
err_msg varchar2(200);
begin
execute immediate 'alter index '||v_index||' rebuild';
exception
when others then
err_msg := TO_CHAR(SQLCODE) || ':' || SQLERRM;
insert into log_rebuid (data, mesg_err) values (sysdate, 'INDEX '||err_msg );
end ;
It rebuilds the index on a table. Be careful because on a 24/7 database, it puts a lock on a table until the index is rebuilt. If it's a big index then you might have some locks on the database.
Monday, 25 October 2010
how to monitor tablespaces using sql
I usually monitor tablespaces using Toad, it has a nice graphical way of showing the tablespaces in DATABASE -> ADMINISTER -> TABLESPACES menu, and SCHEMA BROWSER ->TABLESPACES to get a better view at the datafiles.
This is a different way of monitoring tablespaces. The following sql shows a complete report of the tablespaces of your database ordered by the free space percentage:
select sel1.*
, sel2. autoextensible
from(
SELECT a.tablespace_name,
ROUND (a.bytes_alloc / 1024 / 1024) megs_alloc,
ROUND (NVL (b.bytes_free, 0) / 1024 / 1024) megs_free,
ROUND ( (a.bytes_alloc - NVL (b.bytes_free, 0)) / 1024 / 1024)
megs_used,
ROUND ( (NVL (b.bytes_free, 0) / a.bytes_alloc) * 100) Pct_Free,
100 - ROUND ( (NVL (b.bytes_free, 0) / a.bytes_alloc) * 100) Pct_used,
ROUND (maxbytes / 1048576) MAX
FROM ( SELECT f.tablespace_name,
SUM (f.bytes) bytes_alloc,
SUM (
DECODE (f.autoextensible,
'YES', f.maxbytes,
'NO', f.bytes))
maxbytes
FROM dba_data_files f
GROUP BY tablespace_name) a,
( SELECT f.tablespace_name, SUM (f.bytes) bytes_free
FROM dba_free_space f
GROUP BY tablespace_name) b
WHERE a.tablespace_name = b.tablespace_name(+)
UNION ALL
SELECT h.tablespace_name,
ROUND (SUM (h.bytes_free + h.bytes_used) / 1048576) megs_alloc,
ROUND (
SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ 1048576)
megs_free,
ROUND (SUM (NVL (p.bytes_used, 0)) / 1048576) megs_used,
ROUND (
(SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ SUM (h.bytes_used + h.bytes_free))
* 100)
Pct_Free,
100
- ROUND (
(SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ SUM (h.bytes_used + h.bytes_free))
* 100)
pct_used,
ROUND (SUM (f.maxbytes) / 1048576) MAX
FROM sys.v_$TEMP_SPACE_HEADER h,
sys.v_$Temp_extent_pool p,
dba_temp_files f
WHERE p.file_id(+) = h.file_id
AND p.tablespace_name(+) = h.tablespace_name
AND f.file_id = h.file_id
AND f.tablespace_name = h.tablespace_name
GROUP BY h.tablespace_name
) sel1,
( select max(autoextensible) autoextensible, tablespace_name from dba_data_files group by tablespace_name
union all
select max(autoextensible) autoextensible, tablespace_name from dba_temp_files group by tablespace_name) sel2
where sel1.tablespace_name= sel2.tablespace_name
ORDER BY 5 asc, max desc
You can find this sql and many other useful ones on this post: http://oracle-core-dba.blogspot.com/2008/01/cool-scripts-for-daily-dba-activities.html.
If you want next to see details of a certain tablespace you can use this sql:
select df.TABLESPACE_NAME, df.FILE_NAME, df.FILE_ID, df.STATUS, df.ONLINE_STATUS ,df.AUTOEXTENSIBLE , DF.USER_BYTES MAX_BYTES, SUM (fS.bytes) BYTES_FREE
from dba_data_files df, dba_free_space fs
WHERE df.tablespace_name = fs.tablespace_name(+)
and df.file_id=fs.file_id(+)
and df.TABLESPACE_NAME='USERS'
GROUP BY df.TABLESPACE_NAME, df.FILE_NAME, df.FILE_ID, df.STATUS, df.ONLINE_STATUS ,df.AUTOEXTENSIBLE , DF.USER_BYTES
This is a handy way to monitor your tablespaces especially if you want to build a report concerning the tablespaces and datafiles.
This is a different way of monitoring tablespaces. The following sql shows a complete report of the tablespaces of your database ordered by the free space percentage:
select sel1.*
, sel2. autoextensible
from(
SELECT a.tablespace_name,
ROUND (a.bytes_alloc / 1024 / 1024) megs_alloc,
ROUND (NVL (b.bytes_free, 0) / 1024 / 1024) megs_free,
ROUND ( (a.bytes_alloc - NVL (b.bytes_free, 0)) / 1024 / 1024)
megs_used,
ROUND ( (NVL (b.bytes_free, 0) / a.bytes_alloc) * 100) Pct_Free,
100 - ROUND ( (NVL (b.bytes_free, 0) / a.bytes_alloc) * 100) Pct_used,
ROUND (maxbytes / 1048576) MAX
FROM ( SELECT f.tablespace_name,
SUM (f.bytes) bytes_alloc,
SUM (
DECODE (f.autoextensible,
'YES', f.maxbytes,
'NO', f.bytes))
maxbytes
FROM dba_data_files f
GROUP BY tablespace_name) a,
( SELECT f.tablespace_name, SUM (f.bytes) bytes_free
FROM dba_free_space f
GROUP BY tablespace_name) b
WHERE a.tablespace_name = b.tablespace_name(+)
UNION ALL
SELECT h.tablespace_name,
ROUND (SUM (h.bytes_free + h.bytes_used) / 1048576) megs_alloc,
ROUND (
SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ 1048576)
megs_free,
ROUND (SUM (NVL (p.bytes_used, 0)) / 1048576) megs_used,
ROUND (
(SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ SUM (h.bytes_used + h.bytes_free))
* 100)
Pct_Free,
100
- ROUND (
(SUM ( (h.bytes_free + h.bytes_used) - NVL (p.bytes_used, 0))
/ SUM (h.bytes_used + h.bytes_free))
* 100)
pct_used,
ROUND (SUM (f.maxbytes) / 1048576) MAX
FROM sys.v_$TEMP_SPACE_HEADER h,
sys.v_$Temp_extent_pool p,
dba_temp_files f
WHERE p.file_id(+) = h.file_id
AND p.tablespace_name(+) = h.tablespace_name
AND f.file_id = h.file_id
AND f.tablespace_name = h.tablespace_name
GROUP BY h.tablespace_name
) sel1,
( select max(autoextensible) autoextensible, tablespace_name from dba_data_files group by tablespace_name
union all
select max(autoextensible) autoextensible, tablespace_name from dba_temp_files group by tablespace_name) sel2
where sel1.tablespace_name= sel2.tablespace_name
ORDER BY 5 asc, max desc
You can find this sql and many other useful ones on this post: http://oracle-core-dba.blogspot.com/2008/01/cool-scripts-for-daily-dba-activities.html.
If you want next to see details of a certain tablespace you can use this sql:
select df.TABLESPACE_NAME, df.FILE_NAME, df.FILE_ID, df.STATUS, df.ONLINE_STATUS ,df.AUTOEXTENSIBLE , DF.USER_BYTES MAX_BYTES, SUM (fS.bytes) BYTES_FREE
from dba_data_files df, dba_free_space fs
WHERE df.tablespace_name = fs.tablespace_name(+)
and df.file_id=fs.file_id(+)
and df.TABLESPACE_NAME='USERS'
GROUP BY df.TABLESPACE_NAME, df.FILE_NAME, df.FILE_ID, df.STATUS, df.ONLINE_STATUS ,df.AUTOEXTENSIBLE , DF.USER_BYTES
This is a handy way to monitor your tablespaces especially if you want to build a report concerning the tablespaces and datafiles.
Thursday, 21 October 2010
how to log exceptions in a pl/sql procedure
Logging errors in plsql procedures is a very important debugging factor especially if the procedure is used in night jobs. If a night job fails, in the morning it's best that you know why the procedure hang, and what has it done until it hang.
First of all create a log table:
CREATE TABLE AM_ERROR_LOG
(
ERROR_SQL VARCHAR2(4000 BYTE),
DATE_RUN DATE DEFAULT SYSDATE,
NAMEPROCEDURE VARCHAR2(200 BYTE),
ERROR VARCHAR2(1000 BYTE)
)
;
It's best that this table is on another schema (a log schema), and especially on another tablespace (a log tablespace). Because this is a log table, and there are many inserts on it, and doesn't have to be that fast, it is best not to have indexes.
Then create a procedure like this one:
CREATE OR REPLACE PROCEDURE p_am_log_err (
sqlstr VARCHAR2,
datee DATE,
proc_name VARCHAR2,
err VARCHAR2
)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO AM_ERROR_LOG
(ERROR_SQL, date_run, nameprocedure, ERROR
)
VALUES (sqlstr, datee, proc_name, err
);
COMMIT;
END;
/
The important thig here is that this procedure has PRAGMA AUTONOMOUS_TRANSACTION this means that the commit here doesn't affect other transactions.
Here is an example on how to use the above procedure:
CREATE OR REPLACE PROCEDURE P_night_job_proc()
IS
errMsg VARCHAR2(4000);
BEGIN
---------------------------- procedure body
begin
-----------------------internal plsql block
COMMIT;
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
p_am_log_err('current running sql', sysdate, 'CALCUL_CHEI', errMsg);
end;
COMMIT;
-------------------- end of procedure body
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
p_am_log_err('another running sql', sysdate, 'CALCUL_CHEI', errMsg);
END P_night_job_proc;
/
Of course WHEN OTHERS THEN is a very general and easy way to capture an exception. Still it's best practice to capture exceptions and insert them in a log table especially for key procedures.
First of all create a log table:
CREATE TABLE AM_ERROR_LOG
(
ERROR_SQL VARCHAR2(4000 BYTE),
DATE_RUN DATE DEFAULT SYSDATE,
NAMEPROCEDURE VARCHAR2(200 BYTE),
ERROR VARCHAR2(1000 BYTE)
)
;
It's best that this table is on another schema (a log schema), and especially on another tablespace (a log tablespace). Because this is a log table, and there are many inserts on it, and doesn't have to be that fast, it is best not to have indexes.
Then create a procedure like this one:
CREATE OR REPLACE PROCEDURE p_am_log_err (
sqlstr VARCHAR2,
datee DATE,
proc_name VARCHAR2,
err VARCHAR2
)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO AM_ERROR_LOG
(ERROR_SQL, date_run, nameprocedure, ERROR
)
VALUES (sqlstr, datee, proc_name, err
);
COMMIT;
END;
/
The important thig here is that this procedure has PRAGMA AUTONOMOUS_TRANSACTION this means that the commit here doesn't affect other transactions.
Here is an example on how to use the above procedure:
CREATE OR REPLACE PROCEDURE P_night_job_proc()
IS
errMsg VARCHAR2(4000);
BEGIN
---------------------------- procedure body
begin
-----------------------internal plsql block
COMMIT;
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
p_am_log_err('current running sql', sysdate, 'CALCUL_CHEI', errMsg);
end;
COMMIT;
-------------------- end of procedure body
EXCEPTION
WHEN OTHERS THEN
errMsg := SQLERRM;
p_am_log_err('another running sql', sysdate, 'CALCUL_CHEI', errMsg);
END P_night_job_proc;
/
Of course WHEN OTHERS THEN is a very general and easy way to capture an exception. Still it's best practice to capture exceptions and insert them in a log table especially for key procedures.
Wednesday, 20 October 2010
how to stop an Oracle dbms_job
A dbms_job is created like this:
DECLARE
X NUMBER;
BEGIN
DBMS_JOB.SUBMIT
( job => X
,what => 'My_procedure;'
,next_date => to_date('21/10/2010 03:00:00','dd/mm/yyyy hh24:mi:ss')
,interval => 'TRUNC(sysdate)+1+3/24'
,no_parse => FALSE
);
DBMS_OUTPUT.PUT_LINE('Job Number is: ' || to_char(x));
COMMIT;
END;
This one usually runs at 3 AM, calling the procedure "My_procedure". The thing for the dbms_jobs is that you can set them to run repeatably any time you like.
But when the procedure it calls, hangs, it becomes a bit of a trick. For this example if the procedure hangs, in v$session you can see an active session running a certain sql (in most of the times it's blocking other sessions). If you try to kill the session, in a couple of minutes it appears again. This is the usual behavior of a dbms_job, if the session is killed it starts over and over again until the procedure is successfully done.
To be certain that you have any jobs running, you can run this sql:
SELECT r.sid, r.job, r.this_date, r.this_sec, what
FROM dba_jobs_running r,dba_jobs j
WHERE r.job = j.job
AND j.broken ='N';
To stop the Oracle dbms_job you must issue the following:
BEGIN
DBMS_JOB.broken
( job =>2 -- this is the job number assigned above
,broken => TRUE
);
COMMIT;
END;
Right now you can kill the session if it's doing too much damage to the database. I recommend that you look into the procedure, or into the table of logged exceptions (maybe I'll write a post on how to log all the exceptions in a procedure).
After you are convinced that it's OK to bring the job online issue the following:
BEGIN
DBMS_JOB.broken
( job =>2
,broken => FALSE
);
COMMIT;
END;
When you issue this command, the job starts running again. In many situations this is not a desirable thing. That's why, when I usually have a hang night job, I prefer to reschedule the job for the next day in staid of setting it to broken. This sql should do it:
BEGIN
DBMS_JOB.CHANGE
(
job => 2
,what => 'My_procedure;'
,next_date => to_date('22/10/2010 03:00:00','dd/mm/yyyy hh24:mi:ss')
,interval => 'TRUNC(sysdate)+1+3/24'
);
END;
Then a can kill the session, so it will not reappear until it's scheduled. Be careful how you rewrite your procedure so that the next day it wont happen again.
DECLARE
X NUMBER;
BEGIN
DBMS_JOB.SUBMIT
( job => X
,what => 'My_procedure;'
,next_date => to_date('21/10/2010 03:00:00','dd/mm/yyyy hh24:mi:ss')
,interval => 'TRUNC(sysdate)+1+3/24'
,no_parse => FALSE
);
DBMS_OUTPUT.PUT_LINE('Job Number is: ' || to_char(x));
COMMIT;
END;
This one usually runs at 3 AM, calling the procedure "My_procedure". The thing for the dbms_jobs is that you can set them to run repeatably any time you like.
But when the procedure it calls, hangs, it becomes a bit of a trick. For this example if the procedure hangs, in v$session you can see an active session running a certain sql (in most of the times it's blocking other sessions). If you try to kill the session, in a couple of minutes it appears again. This is the usual behavior of a dbms_job, if the session is killed it starts over and over again until the procedure is successfully done.
To be certain that you have any jobs running, you can run this sql:
SELECT r.sid, r.job, r.this_date, r.this_sec, what
FROM dba_jobs_running r,dba_jobs j
WHERE r.job = j.job
AND j.broken ='N';
To stop the Oracle dbms_job you must issue the following:
BEGIN
DBMS_JOB.broken
( job =>2 -- this is the job number assigned above
,broken => TRUE
);
COMMIT;
END;
Right now you can kill the session if it's doing too much damage to the database. I recommend that you look into the procedure, or into the table of logged exceptions (maybe I'll write a post on how to log all the exceptions in a procedure).
After you are convinced that it's OK to bring the job online issue the following:
BEGIN
DBMS_JOB.broken
( job =>2
,broken => FALSE
);
COMMIT;
END;
When you issue this command, the job starts running again. In many situations this is not a desirable thing. That's why, when I usually have a hang night job, I prefer to reschedule the job for the next day in staid of setting it to broken. This sql should do it:
BEGIN
DBMS_JOB.CHANGE
(
job => 2
,what => 'My_procedure;'
,next_date => to_date('22/10/2010 03:00:00','dd/mm/yyyy hh24:mi:ss')
,interval => 'TRUNC(sysdate)+1+3/24'
);
END;
Then a can kill the session, so it will not reappear until it's scheduled. Be careful how you rewrite your procedure so that the next day it wont happen again.
Tuesday, 19 October 2010
finding blocking sessions
Well I've told you how to kill a session from the database, whatever the reason. One of the reasons may be because it's a blocking session.
There are many ways of finding blocking sessions. I personally use Toad for Oracle for browsing the database, it has a Session Browser, and a Locks tab to find locking sessions.
Also the following sql will give you the waiting and holding sessions on your instance:
SELECT w.*,
(SELECT status
FROM v$session ses
WHERE ses.sid = w.holding_session)
holding_ses_status,
(SELECT sql_text
FROM v$session ses, v$sql sq
WHERE ses.sql_address = sq.address
and ses.sql_hash_value=sq.hash_value
AND ses.sid = w.waiting_session
AND ROWNUM = 1)
waiting_sql,
(SELECT sql_text
FROM v$session ses, v$sql sq
WHERE ses.sql_address = sq.address
and ses.sql_hash_value=sq.hash_value
AND ses.sid = w.holding_session
AND ROWNUM = 1)
holding_sql
FROM dba_waiters w
This sql will give you both the ORACLE SID of both the sessions and the current sql both of them are currently running.
If you want to detect developer sessions on the production database, the following sql can be used:
select ses.sid,pr.spid, ses.status, ses.schemaname, ses.machine, ses.terminal, ses.osuser,ses.program,ses.module, ses.action , ses.logon_time
from v$session ses,
v$process pr
where ses.paddr=pr.addr
and lower(ses.program) in ('plsqldev.exe','toad.exe','sql developer')
order by pr.pga_used_mem desc
It depends on the company profile if you are allowed or not to kill sessions, it's better to know that before you try to kill any session, or sometimes it's better to give them a report with what session is holding another session.
There are many ways of finding blocking sessions. I personally use Toad for Oracle for browsing the database, it has a Session Browser, and a Locks tab to find locking sessions.
Also the following sql will give you the waiting and holding sessions on your instance:
SELECT w.*,
(SELECT status
FROM v$session ses
WHERE ses.sid = w.holding_session)
holding_ses_status,
(SELECT sql_text
FROM v$session ses, v$sql sq
WHERE ses.sql_address = sq.address
and ses.sql_hash_value=sq.hash_value
AND ses.sid = w.waiting_session
AND ROWNUM = 1)
waiting_sql,
(SELECT sql_text
FROM v$session ses, v$sql sq
WHERE ses.sql_address = sq.address
and ses.sql_hash_value=sq.hash_value
AND ses.sid = w.holding_session
AND ROWNUM = 1)
holding_sql
FROM dba_waiters w
This sql will give you both the ORACLE SID of both the sessions and the current sql both of them are currently running.
If you want to detect developer sessions on the production database, the following sql can be used:
select ses.sid,pr.spid, ses.status, ses.schemaname, ses.machine, ses.terminal, ses.osuser,ses.program,ses.module, ses.action , ses.logon_time
from v$session ses,
v$process pr
where ses.paddr=pr.addr
and lower(ses.program) in ('plsqldev.exe','toad.exe','sql developer')
order by pr.pga_used_mem desc
It depends on the company profile if you are allowed or not to kill sessions, it's better to know that before you try to kill any session, or sometimes it's better to give them a report with what session is holding another session.
Monday, 18 October 2010
how to kill an Oracle session
If I want to kill an Oracle database session, in a UNIX environment, I usually do it like this:
1. I take the sessions SPID from an sql like this one:
SELECT ses.sid,
ses.username,
ses.status,
pr.spid
FROM v$session ses, v$process pr
WHERE ses.paddr = pr.addr
Or with any other method to see the sessions SID and SPID.
Note down the SPID for the respective SID
2. Connect to the OS with a terminal and run the following command:
kill -9 noted_spid
The thing is that every session in the database is a process in the OS, on a DEDICATED server. So it can be killed from the OS directly.
1. I take the sessions SPID from an sql like this one:
SELECT ses.sid,
ses.username,
ses.status,
pr.spid
FROM v$session ses, v$process pr
WHERE ses.paddr = pr.addr
Or with any other method to see the sessions SID and SPID.
Note down the SPID for the respective SID
2. Connect to the OS with a terminal and run the following command:
kill -9 noted_spid
The thing is that every session in the database is a process in the OS, on a DEDICATED server. So it can be killed from the OS directly.
Subscribe to:
Posts (Atom)