Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Sudhanshu.

Asked: October 17, 2002 - 9:20 am UTC

Last updated: June 12, 2023 - 12:45 pm UTC

Version: 8.1.7

Viewed 50K+ times! This question is

You Asked

Any comment on this weird behaviour :-

SQL> exec dbms_lock.sleep(3500);

PL/SQL procedure successfully completed.

Elapsed: 00:08:14.18
SQL> exec dbms_lock.sleep(1000);

PL/SQL procedure successfully completed.

Elapsed: 00:03:48.71
SQL> exec dbms_lock.sleep(600);

PL/SQL procedure successfully completed.

Elapsed: 00:09:41.12

Does this mean that dbms_lock.sleep is unreliable ?

Thanks
Suds

and Tom said...

I think it means you have a TON more patience then I ever would in a billion years.... I cannot believe you waited 8 hours....


There is an issue with really large sleep times. Suggest you sleep no more then 10 minutes or so and for larger "sleeps", loop it, something like this:

create procedure my_sleep( SLEEP_TIME IN NUMBER )
as
begin

for i in 1 .. trunc( SLEEP_TIME/600 )
loop
dbms_lock.sleep( 600 );
end loop;
dbms_lock.sleep( SLEEP_TIME-trunc(SLEEP_TIME/600)*600 );

end;
/

Rating

  (36 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Sudhanshu Kumar, October 17, 2002 - 11:19 pm UTC

Thanks Tom for the loop idea.

But the timing 00:08:14.18 means 8 minutes & 14 seconds.And I think sqlplus have this default format of giving hundreth of a second when we do set timing on. So that means I only waited for 8 minutes.


Tom Kyte
October 18, 2002 - 8:50 am UTC

DOH -- i read that wrong didn't I.

but yes, dbms_lock.sleep has problems with really large numbers -- the loop will correct that.

DBMS_LOCK package

Denise, October 23, 2003 - 12:02 pm UTC

Hi Tom

I seem to be pestering you alot these days.

I have a lock on a table that I am trying to figure out
how to release.(see v$lock output)


Oracle usercode                Oracle SID Serial nbr Object name     Lock type     F_ground  B_groun
------------------------------ ---------- ---------- --------------- ------------- --------- -------
GUI                                     8          3 MAILING         Row-X (SX)              188

SQL> select * from v$lock where sid = 8;

Thu Oct 23                                                                                              
                                                         Exclusive locks

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
3A330458 3A330524          8 TX     131138     177618          6          0       6346          0
1D8016AC 1D8016C0          8 TM      65920          0          3          0       6361          0
1D0EAA18 1D0EAA28          8 JQ          0      19148          6          0       6524          0


I ran the dbms_lock.sql to create the dbms_lock package.

I then researched the functions used to allocate,request,convert and release locks.

when I run the dbms_lock.allocate_unique function I keep
getting the following errors.

SQL> EXEC SQL EXECUTE
BEGIN SQL EXECUTE; END;

          *
ERROR at line 1:
ORA-06550: line 1, column 11:
PLS-00103: Encountered the symbol "EXECUTE" when expecting one of the following:
%
The symbol "%" was substituted for "EXECUTE" to continue.


SQL> BEGIN
  2     DBMS_LOCK.ALLOCATE_UNIQUE (lockname IN VARCHAR2,
  3                                lockhandle OUT VARCHAR2); 
  4  END; 
  5  /
   DBMS_LOCK.ALLOCATE_UNIQUE (lockname IN VARCHAR2,
                                          *
ERROR at line 2:
ORA-06550: line 2, column 43:
PLS-00103: Encountered the symbol "VARCHAR2" when expecting one of the following:
(
ORA-06550: line 3, column 55:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
return

I have an ora-00054 "Resource Busy with acquire NOWAIT specified" that I am trying to clear(or release) from the 
system)

as always thanks a heap for your time and help.



 

Tom Kyte
October 23, 2003 - 1:21 pm UTC

kill session '8,3', thats the only way to release locks in another session

DUH!!!

Denise, October 23, 2003 - 2:35 pm UTC

you know Tom...right after I wrote you I ran this Kill Session script I have that I use to monitor sessions.

I saw that 'locked table' session still hanging out there
and thought...heck...I'm gonna type:

alter system kill session '8,3' immediate;

wa-la the session was slated marked for kill...thought
"ok it's doing the rollback thing..I'll wait awhile"...
looked back and the session was gone and the table was
no longer locked.

Like I said before I always seem to make things
harder than they are...but it's how I learn.

I promise not to pester you(at least for awhile) :~)

regards,
your biggest oracle fan





DBMS_LOCK.SLEEP problems

A reader, June 30, 2005 - 10:05 am UTC

Found this recomendation recently: </code> http://www.chrispoole.co.uk/tips/plsqltip1.htm <code>

Do you have any comments?
Thanks a lot

Tom Kyte
June 30, 2005 - 10:21 am UTC

do you need to sleep for more than 10 minutes?

DBMS_LOCK.SLEEP problems

A reader, July 05, 2005 - 3:44 pm UTC

This is the problem that we are solving by calling SLEEP with much more than 10 minutes:
Audit procedure runs inside of Oracle. Procedure is getting data through webservice calls to some legacy system and then storing data locally in Oracle. Legacy system is available from 6am till 6pm. Audit can run for hours (for really large data sets - even days. Performance is beyond of us - it's all on the legacy system side). We found the easiest way to solve the problem: schedule procedure to run and periodically check current time between webservice calls. When legacy system is unavailable, procedure is just sleeping till next available working window... Please advice if this is a reasonable approach or it can be done smarter.
Thanks a lot!

Tom Kyte
July 05, 2005 - 3:53 pm UTC

why not just schedule it to run at the next available window? eg: dbms_job.

zero percent chance I would have a session just sleep there for hours on end.

DBMS_LOCK.SLEEP problems

A reader, July 06, 2005 - 2:55 pm UTC

What if this must be done as one transaction?

Tom Kyte
July 07, 2005 - 8:23 am UTC

you have a transaction that runs for hours and hours and hours or days even???

and you've never had serious rollback/undo segment issues?? really?

dbms_lock.sleep procedure

A reader, July 07, 2005 - 11:17 am UTC

To be honest - no. Audit data retrieved from legacy system is completely isolated and is not used till the audit is done. But I see your concern. So - if I understand you right - you'd definitely prefer splitting such a job to multiple transactions.
By the way - it's typical for this webservice call to run for an hour or more...

Tom Kyte
July 07, 2005 - 1:36 pm UTC

.... it's typical for this webservice call to run for an hour or more......

wow, thats not a webservice anymore :)

definitely split this into logical units of work -- but I cannot imagine hanging out for hours and hours - the odds that your open transaction fails goes up with every hour (system failure, whatever). I don't know your system -- but I would look at the business logic.

How about for smaller duration?

A reader, May 03, 2006 - 9:58 am UTC

Hi Tom,

How accurate is dbms_lock.sleep with smaller duration?

Please consider the following test case:

Version: 9.2.0.6

create table tmp_test (log_dt date not null, id number not null);

begin
for i in 1..3*60*60 loop
insert into tmp_test (log_dt,id) values (sysdate,1);
commit;
dbms_lock.sleep(1);
end loop;
end;
/

select *
from (select x.*, (log_dt - prev_log_dt) * 24 * 60 * 60 as seconds
from (select lag(log_dt) over(order by log_dt) as prev_log_dt, t.*
from test.tmp_test t
where t.id = 1) x)
where seconds > 1
order by log_dt desc
/

PREV_LOG_DT LOG_DT ID SECONDS
3/5/2006 9:42:37 PM 3/5/2006 9:42:39 PM 1 2
3/5/2006 9:41:26 PM 3/5/2006 9:41:28 PM 1 2
3/5/2006 9:40:30 PM 3/5/2006 9:40:32 PM 1 2
3/5/2006 9:39:38 PM 3/5/2006 9:39:40 PM 1 2
3/5/2006 9:38:32 PM 3/5/2006 9:38:34 PM 1 2
3/5/2006 9:37:26 PM 3/5/2006 9:37:28 PM 1 2
3/5/2006 9:36:24 PM 3/5/2006 9:36:26 PM 1 2
3/5/2006 9:35:38 PM 3/5/2006 9:35:40 PM 1 2
3/5/2006 9:34:23 PM 3/5/2006 9:34:25 PM 1 2
...

Even I can find,

select *
from (select x.*, (log_dt - prev_log_dt) * 24 * 60 * 60 as seconds
from (select lag(log_dt) over(order by log_dt) as prev_log_dt, t.*
from test.tmp_test t
where t.id = 1) x)
where seconds > 2
order by log_dt desc
/

PREV_LOG_DT LOG_DT ID SECONDS
3/5/2006 8:57:28 PM 3/5/2006 8:57:38 PM 1 10
3/5/2006 8:48:25 PM 3/5/2006 8:48:28 PM 1 3


I had also captured v$session_wait for this session in another table for every 5 seconds. During the 10 seconds gap, I see only the following:

LOG_DT SID SEQ# EVENT P1TEXT P1 P1RAW P2TEXT P2 P2RAW P3TEXT P3 P3RAW WAIT_TIME SECONDS_IN_WAIT STATE
3/5/2006 8:57:40 PM 126 19587 PL/SQL lock timer duration 100 0000000000000064 0 00 0 00 0 2 WAITING
3/5/2006 8:57:35 PM 126 19584 PL/SQL lock timer duration 100 0000000000000064 0 00 0 00 0 26 WAITING
3/5/2006 8:57:30 PM 126 19584 PL/SQL lock timer duration 100 0000000000000064 0 00 0 00 0 21 WAITING
3/5/2006 8:57:25 PM 126 19581 PL/SQL lock timer duration 100 0000000000000064 0 00 0 00 0 16 WAITING

The wait event is always this.

Does this mean there is some issue with the database server?

Thanks always.

Regards,

Albert Nelson A.

Tom Kyte
May 03, 2006 - 1:00 pm UTC

well, the 2 second ones - I'd ignore all of them, just takes a sleep of 1.000000000001 second to cause that (give you are using sysdate with a granularity of 1 second - anything even a TINY BIT over 1 second could be "2 seconds"

according to your wait report - you'd have a bigger than 10 second gap there - look at the 8:57:35 observation - seconds in wait = 26. are you sure that you were looking at the right sessions here.


(also, what is the goal of this test - is dbms_lock.sleep going to be precise within +/- 0.0000000001 seconds - never, nope, doubt it. Will it be "pretty close", yup, yes - absolutely)

Why gap?

Albert Nelson A, May 03, 2006 - 2:15 pm UTC

Hi Tom,

I agree with the 2 seconds gap.

I was also very much puzzled with seconds in wait. But I am sure that this is the correct session.

Actually the goal of the test is as below:

We have a table that is supposed to be inserted with about 50 records per second by the application. Of late, we see for few seconds (about 30 to 40) there are no records in the table. This gap is seen about 20 times daily. We are trying to figure it out what is the root cause of this. Is the application itself not inserting the data or the application is sending the inserts but the database is not doing it? That's why I created this test case.

Your advice will be very much helpful for us.

Thanks always.

Regards,

Albert Nelson A.



Tom Kyte
May 03, 2006 - 2:54 pm UTC

look in your alert - any "checkpoint not complete" messages there?

No

Albert Nelson A., May 03, 2006 - 9:23 pm UTC

Hi Tom,

There are no error messages in the alert log.

Albert Nelson A.

Tom Kyte
May 04, 2006 - 2:11 am UTC

that would be the only thing I can think of off of the top of my head - that the database "paused" while dbwr finished a checkpoint OR while arch got caught up (cannot allocate new log messages - the database could "pause" during those events, the inserts would stop).

The information above just isn't adding up - if the session was 26 seconds in wait:

3/5/2006 8:57:35 PM 126 19584 PL/SQL lock timer duration 100
0000000000000064 0 00 0 00 0 26 WAITING

at 8:57:35 - I don't see how this bit of data:

PREV_LOG_DT LOG_DT ID SECONDS
3/5/2006 8:57:28 PM 3/5/2006 8:57:38 PM 1 10

could have been produced by it - because it was asleep at 8:57:28.

Is dbms_lock.sleep uninterruptible?

Roman Filipsky, May 04, 2006 - 6:19 am UTC

Here's the testcase (both 9i and 10g):
Login to sqlplus and do:
exec dbms_lock.sleep(100)

Try to cancel it using CtrlC. It's succesful.
Now when the sleep is placed inside the loop like in:
begin
loop
dbms_lock.sleep(100);
end loop;
end;
/

That block cant be interrupted with CtrlC. The problem is that it cant be interrupted using OCI from another thread as well.
Do you know about any workaround?


Tom Kyte
May 04, 2006 - 7:41 am UTC

no, i do not.

Time to call support?

Albert Nelson A, May 04, 2006 - 7:32 am UTC

Hi Tom,

Yes I find this anomaly.

Even some times, the session_wait shows a continuous increase in seconds_in_wait but during that time I can find records inserted. I had also confirmed that the session id is the correct one.

LOG_DT SID SEQ# EVENT P1TEXT P1 P1RAW SECONDS_IN_WAIT STATE
3/5/2006 8:47:38 PM 126 18966 PL/SQL lock timer duration 100 0000000000000064 118 WAITING
3/5/2006 8:47:33 PM 126 18961 PL/SQL lock timer duration 100 0000000000000064 113 WAITING
3/5/2006 8:47:28 PM 126 18956 PL/SQL lock timer duration 100 0000000000000064 108 WAITING
3/5/2006 8:47:23 PM 126 18951 PL/SQL lock timer duration 100 0000000000000064 103 WAITING
3/5/2006 8:47:18 PM 126 18946 PL/SQL lock timer duration 100 0000000000000064 98 WAITING
3/5/2006 8:47:13 PM 126 18942 PL/SQL lock timer duration 100 0000000000000064 93 WAITING
3/5/2006 8:47:08 PM 126 18937 PL/SQL lock timer duration 100 0000000000000064 88 WAITING
3/5/2006 8:47:03 PM 126 18932 PL/SQL lock timer duration 100 0000000000000064 83 WAITING
3/5/2006 8:46:58 PM 126 18927 PL/SQL lock timer duration 100 0000000000000064 78 WAITING
3/5/2006 8:46:53 PM 126 18922 PL/SQL lock timer duration 100 0000000000000064 73 WAITING
3/5/2006 8:46:48 PM 126 18917 PL/SQL lock timer duration 100 0000000000000064 68 WAITING
3/5/2006 8:46:43 PM 126 18912 PL/SQL lock timer duration 100 0000000000000064 63 WAITING
3/5/2006 8:46:38 PM 126 18907 PL/SQL lock timer duration 100 0000000000000064 58 WAITING
3/5/2006 8:46:33 PM 126 18902 PL/SQL lock timer duration 100 0000000000000064 53 WAITING
3/5/2006 8:46:28 PM 126 18897 PL/SQL lock timer duration 100 0000000000000064 48 WAITING
3/5/2006 8:46:23 PM 126 18892 PL/SQL lock timer duration 100 0000000000000064 43 WAITING
3/5/2006 8:46:18 PM 126 18887 PL/SQL lock timer duration 100 0000000000000064 38 WAITING
3/5/2006 8:46:13 PM 126 18882 PL/SQL lock timer duration 100 0000000000000064 33 WAITING
3/5/2006 8:46:08 PM 126 18877 PL/SQL lock timer duration 100 0000000000000064 28 WAITING
3/5/2006 8:46:03 PM 126 18872 PL/SQL lock timer duration 100 0000000000000064 23 WAITING
3/5/2006 8:45:58 PM 126 18867 PL/SQL lock timer duration 100 0000000000000064 18 WAITING
3/5/2006 8:45:53 PM 126 18862 PL/SQL lock timer duration 100 0000000000000064 13 WAITING
3/5/2006 8:45:48 PM 126 18858 PL/SQL lock timer duration 100 0000000000000064 8 WAITING
3/5/2006 8:45:43 PM 126 18853 PL/SQL lock timer duration 100 0000000000000064 3 WAITING

Log_dt id
1 3/5/2006 8:47:38 PM 1
2 3/5/2006 8:47:37 PM 1
3 3/5/2006 8:47:35 PM 1
4 3/5/2006 8:47:34 PM 1
5 3/5/2006 8:47:33 PM 1
6 3/5/2006 8:47:32 PM 1
7 3/5/2006 8:47:31 PM 1
8 3/5/2006 8:47:30 PM 1
9 3/5/2006 8:47:29 PM 1
10 3/5/2006 8:47:28 PM 1
... Deleted for brevity
113 3/5/2006 8:45:44 PM 1
114 3/5/2006 8:45:43 PM 1

Time to call support?

Regards,

Albert Nelson A.

Tom Kyte
May 04, 2006 - 7:54 am UTC

could be - but - do you care in this case? (since it is not the problem you are trying to solve in the first place...)

No.

Albert Nelson A, May 04, 2006 - 8:59 am UTC

Hi Tom,

Actually I don't care for the present case. But just that may be a possible bug be pointed out.

Any other suggestions for finding out the reason for gap?

Thanks always.

Regards,

Albert Nelson A.

Tom Kyte
May 04, 2006 - 4:37 pm UTC

have you tried the approach you are using against your dummy plsql block against this application (a process to monitor what it is doing from another session)

Analysis

Albert Nelson A, May 05, 2006 - 7:28 am UTC

Hi Tom,

Actually I had captured v$session_wait for all the sessions when I ran the test case.

The application is using connection pool and hence I cannot take identify a particular session.

The application table had seven gaps during that time. I had tried the following query for some gap periods:

select event, count(distinct sid), sum(seconds_in_wait)
from test.sw
where log_dt between
to_date('3/5/2006 8:21:46 PM', 'dd/mm/yyyy hh:mi:ss am') and
to_date('3/5/2006 8:22:49 PM', 'dd/mm/yyyy hh:mi:ss am') and
sid > 11
group by event
/
EVENT COUNT(DISTINCTSID) SUM(SECONDS_IN_WAIT)
PL/SQL lock timer 2 192
SQL*Net message from client 187 6572781
SQL*Net message to client 1 0
buffer busy waits 1 0
db file sequential read 3 0
log file sync 116 0

between
to_date('3/5/2006 8:44:09 PM', 'dd/mm/yyyy hh:mi:ss am') and
to_date('3/5/2006 8:44:59 PM', 'dd/mm/yyyy hh:mi:ss am')

EVENT COUNT(DISTINCTSID) SUM(SECONDS_IN_WAIT)
PL/SQL lock timer 2 620
SQL*Net message from client 201 4688077
SQL*Net message to client 1 0
db file sequential read 1 0
log file sync 126 50

between
to_date('3/5/2006 8:55:03 PM', 'dd/mm/yyyy hh:mi:ss am') and
to_date('3/5/2006 8:55:41 PM', 'dd/mm/yyyy hh:mi:ss am')

EVENT COUNT(DISTINCTSID) SUM(SECONDS_IN_WAIT)
PL/SQL lock timer 2 1656
SQL*Net message from client 221 3646645
SQL*Net message to client 1 0


Does this conclusively prove that application did not sent any insert during that time? Should we concentrate on application / network and rule out database?

Thanks again.

Regards,

Albert Nelson A.

Tom Kyte
May 05, 2006 - 2:36 pm UTC

no, that doesn't prove anything - could be a connection pool issue though - if the application grabs a connect/does something/releases - the connection pool itself could be the "snag" - there might not have been a connection to grab.

be nice if the application called dbms_application_info to identify itself - v$session could be used to figure out "what session is what" then


equivalent SQLPLUS command

abz, June 06, 2007 - 11:43 am UTC

Is there any equivalent SQLPLUS (not pl/sql) command for
the functionality dbms_lock.sleep provides?




Tom Kyte
June 06, 2007 - 9:17 pm UTC

no, just pause.

dbms_sleep.lock doesnt work in mount status

abz, June 06, 2007 - 11:55 am UTC

dbms_sleep.lock doesnt executes when called
when the database is is in mount state.

Any solution to this?

Can I use the undocumented DBMS_BACKUP_RESTORE.SLEEP?
because it even works in mount state. Will there be any harm?



Tom Kyte
June 06, 2007 - 9:18 pm UTC

open the database, not much works in mount but not open state.

what are you trying to do? and why?

I AM USING 10G RELEASE 2

abz, June 06, 2007 - 11:56 am UTC


trying to do this

abz, June 07, 2007 - 4:10 am UTC

Actually, on my primary production database I have
set log_archive_duplex_dest='/mydr_archives', /mydr_archives
is a mapped (using Network File System(NFS)) to another
remote AIX machine.

After every 30 minutes archived are generated and stored
on this location.

On the remote AIX machine I am using
RECOVER AUTOMATIC DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;

But when sometimes it completes before the new file is
arrived, then it requires me to type the command again
when the file is arrived.

What I want is a .SQL script in which I will do
RECOVER AUTOMATIC DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
execute dbms_lock.sleep(600);
RECOVER AUTOMATIC DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
execute dbms_lock.sleep(600);
.
.
.

I would liked a pl/sql loop, but RECOVER is an SQL command so it will not work and even if it worked, then in case
of its failure due to unavailability of the file it will
break the loop. (by the way, is there a way I can run SQLPLUS command from a pl/sql block.)?

I know you may recommend to implement DATA GUARD, but this
is not an option for us for some reason.






Tom Kyte
June 07, 2007 - 2:45 pm UTC

why isn't it an option - of course it is. The right answer is data guard, it IS MOST CERTAINLY AN OPTION.

DBMS_LOCK.SLEEP not working in Mount state

Vikas Khanna, September 26, 2007 - 6:20 am UTC

Hi Tom,

I am trying to flip the Standby from MOUNT to OPEN READ ONLY and vice versa through an automated job, so that query reporting can talk to stanby and can get the reports.

However, while trying to open the database in READ ONLY mode I want to make sure that the difference between the applied VS archived log is not more than 1 log sequence.

If the difference is more than 1, please let the process sleep for 5 mins before checking again from v$managed_standby.

I checked dbms_lock.sleep(n) doesn't work and it says Invalid identifier. Can you please let me know any other way by which a process can be made to sleep for n secs before retrying again the operation when in MOUNTED state.

Thanks
VK
Tom Kyte
September 26, 2007 - 9:37 pm UTC

are you on unix?

SQL> !sleep <whatever>

would work - on windows - we'd need to find another "sleep" method

Vikas Khanna, September 27, 2007 - 12:47 am UTC

Hi Tom,

We are on unix.

However with in PL/SQL code how do I give a host call to let the process sleep for n secs.

declare
Arch_seq NUMBER := 2;
Mrp_seq NUMBER := 0;
begin
-- To check whether we have Applied Vs Archived Status current as of Primary, if not loop through till they are equal-1

While (Arch_seq - Mrp_seq) > 1 loop
for Check_Process in (Select Process, Max(Sequence#) Seq from V\$managed_standby Where Process != 'RFS' Group by Process)
loop
If Check_Process.Process = 'ARCH' then
arch_seq := Check_Process.Seq;
Else
mrp_seq := Check_Process.Seq;
End if;
end loop;
If (Arch_seq - Mrp_seq) > 1 then
dbms_output.put_line('Date : ' || to_Char(sysdate,'dd/mm/yyyy hh24:mi:ss') || ' Waiting for the logs to be applied the difference being ' || (Arch_seq - Mrp_seq) || ' logs');
--dbms_lock.sleep(120);
Else
dbms_output.put_line ('Date : ' || to_Char(sysdate,'dd/mm/yyyy hh24:mi:ss') || ' No Waiting for the logs to be applied');
exit;
End if;
End loop;

Thanks
Tom Kyte
September 27, 2007 - 6:53 am UTC

you will not be doing this in plsql - you will have to script this bit using either sqlplus directly or better yet, an OS specific shell script.

plsql is running in the server, it cannot just 'shell out' from your sqlplus session.

Please help

vk, September 28, 2007 - 2:12 am UTC

Hi Tom,

Since, I am not too good at shell scripts, can you please write this for me as it will provide me a good learning platform to move forward in that direction.

Looking for a response.

Thanks
Tom Kyte
September 28, 2007 - 5:33 pm UTC

this is such an opportunity for you then!

I've always found that a small challenge, something really small and tangible, is a great way to get started.

Me coding a snippet for you - that would not be a good platform to move forward from.

You doing it - that would be.

to vk from INDIA

Tyler, September 28, 2007 - 1:28 pm UTC

How do you expect to get any better at scripting if you get others to do your work for you?

Not trying to be rude, but personally, I'd rather see Tom spending his time helping people with conceptual problems as opposed to doing their homework.

Regards,

Tyler.

To Tyler

Ritesh, September 28, 2007 - 5:29 pm UTC

Not to be harsh!

I think you are acting as you are the boss of Tom, let Tom decide what he has to answer and what not.

It's an open community and people do learn from this site a lot, As VK is having this issue I am also facing the same one.

If Tom is busy then you could help us, if you have the knowledge or else you also learn what Tom has to say.

Thanks,



OPEN to MOUNT State

ritesh, October 05, 2007 - 6:36 am UTC

Hi Tom,

I have written the script in flipping the standby from mount to open (RO) and back from open to mount state.

However the logic states that with in a time frame, if the user session exists doing something, we need to kill and put the database back to mount state for the logs to start applying,

However after killing sessions and initiating the recover manage standby database I am getting this error

ORA-01093: ALTER DATABASE CLOSE only permitted with no sessions connected

Can you please let me know how best to handle this?

V$session entry exists with 'KILLED Status'

ritesh, October 06, 2007 - 5:53 am UTC

Hi Tom,

I checked and found that there is an entry which exists in V$session for that sid which has been killed using 'Alter system kill session ' , ' immediate;

I have also set my sqlnext.expire_time=1 which means that the dead connections (which have been killed) should go off with in a span of 1 minute.

However the session does exist for duration of more than 5 mins till I wrote some SQL statement to get 'your session has been killed' and then the session from V$session went off.

Should sqlnet.expire_time not detect dead sessions and remove their entry from V$session.

Thanks

Please Explain

Bhushan, April 03, 2008 - 11:19 am UTC

Hello Tom,
The concept of Locks seems enchanting :)
Although i have never used it before as a developer neither know who can use it efficiently.
I wrote this piece of code and did see some changes in the dba_ddl_locks view output (using 10g on vista installed 2 days back)which told me atleast the syntax was correct.However i fail to understand how and where it can be used.we neither specify any object or device when requesting a handle? Or is the handle something like a pointer..that is returned from the package and then we use it...dont know myself i am confused.PLease help clarify.

-- Created on 4/3/2008 by BHUSHAN
declare
-- Local variables here
i integer:=180;
test_lock VARCHAR2(100):= 'var1_test_lock';
test_lock_handle VARCHAR2(100);
begin
-- Test statements here
DELETE test WHERE ROWID IN (SELECT ROWID FROM test WHERE rownum < 100);
sys.dbms_lock.allocate_unique(test_lock,test_lock_handle ,i);
dbms_output.put_line(test_lock_handle);

sys.dbms_lock.sleep(60);
end;

Cheers!!!
Bhushan
Tom Kyte
April 03, 2008 - 9:13 pm UTC

it is like a pointer, a handle...

Thanks

Bhushan, April 04, 2008 - 12:13 pm UTC

Could you please give an example?I have your book but did not carry it with me to Singapore.If you can direct me to any link here we can actually see an example that too would be great..i know the syntax and sementics of how we can get the handle..what i want to know is ocne we get the handle how it can be used...

Cheers!!!
Bhushan
Tom Kyte
April 04, 2008 - 1:02 pm UTC

you have access to the online documentation? it weighs nothing.


allocate unique just allocates a named lock (you name it)

You use it in your code to control multiple sessions accessing a resource.

Say you wanted to have many sessions write to the same OS file - that would be a mess normally - so you could:

a) allocate unique( 'filename.goes.here', your_handle )
b) request( your_handle, in exclusive mode ) - that serializes

c) open file in append mode, write message, close file

d) release the lock you obtained in b)






A strange story

Paul, April 24, 2008 - 8:51 am UTC

Thanks for the tip re dbms_lock.sleep. My very odd situation combines several of the ideas of this thread.

The problem: an inhouse forms application has a bug where when the user hits the wrong combination of keystrokes a query like this is fired:

select ....
from matched_invoice_line_items W
for update of keyrec_date nowait;

The table has 25 million rows. The W alias seems to be a truncated where clause. This query starts at the beginning of history and locks every row it can, often reading and locking more than 20 million rows before it finds a locked row and must roll back. Generates a lot of redo in a hurry, 3-5gb isn't unusual.

Development hasn't been able to reproduce the bug, Oracle says upgrade your software to supported versions, etc., mgmt has other things to worry about.

The grotesque workaround is to lock the oldest row in the table during working hours, which causes the query-from-hell to fail immediately. The row needs to be locked 13 hours a day.

So in this odd case we have a need for a very long transaction as was mentioned earlier in this thread as well as the need for dbms_lock.sleep - sleep until the window closes and then exit rollback.

It's so ugly that I had to tell someone about it.





simulating job interval through sleep

Gajanan, August 17, 2009 - 9:15 am UTC

Dear Sir,
I have a procedure, which I, have to schedule once every day, But i am not suppose to use dbms_job or dbms_scheduler, so I, am not sure how to create a interval(similar to the one present in dbms_scheduler), so I plan to do something similar to
loop
pl/sql
dbms_lock.sleep(86400);
end loop;
Question 1) Will giving such a long sleep period create issue.
Question 2) Is there any other alternative?
thank you.
Tom Kyte
August 24, 2009 - 8:51 am UTC

...But i am not
suppose to use dbms_job or dbms_scheduler, ...

so, why are you asking me? The only way to schedule jobs inside the database is....

dbms_job
dbms_scheduler


your approach will never work - since once you shutdown the database your anonymous block goes away.


You know the correct way

dbms_job
dbms_scheduler

there is no reason to NOT use them, use them.

Session state and dbms_lock.sleep

A reader, September 29, 2010 - 10:38 am UTC

Tom,
My assumption is that when you call dbms_lock.sleep that you are actually "doing some work" as far as the session is concerned, you are not idle.

Is this true or not or when you call sleep does Oracle interpret this time as idle ?

Thanks for your response.
Tom Kyte
September 29, 2010 - 10:58 am UTC

your session is active (v$session.status) but you are in an idle wait event (you only incur wait events when active - you are actively waiting :) )

DBMS_LOCK

A Reader, December 15, 2010 - 5:23 am UTC

Hi Tom,

Would it not be better to leave locking to Oracle itself instead of implementing it using DBM_LOCK? Are there any advantages or is it aimed to be used for specific purposes only.

Thanks
Tom Kyte
December 15, 2010 - 11:21 am UTC

it is aimed to be used for special cases only - most people will never have a need for it.

dbms_lock is useful when you need to impose serialization on some process - when you have some shared resource not protected by normal enqueue (row) locks. For example - maybe you have a logging routine you built - it logs to a file. You have decided that all of your processes should log to the same file (maybe they just write start/end times or something like that). dbms_lock would be useful to ensure that only one transaction at a time tried to open the file/write it/close it.

dbms_lock from Expert one-on-one Oracle

Rajeshwaran, Jeyabal, January 24, 2011 - 8:45 am UTC

Tom:

I am reading about dbms_lock API from Expert one-on-one Oracle Appendix AG: DBMS_LOCK.

tkyte@TKYTE816> create or replace trigger demo_bifer
2 before insert on demo
3 for each row
4 declare
5 l_lock_id number;
6 resource_busy exception;
7 pragma exception_init( resource_busy, -54 );
8 begin
9 l_lock_id :=
10 dbms_utility.get_hash_value( to_char( :new.x ), 0, 1024 );
11
12 if ( dbms_lock.request
13 ( id => l_lock_id,
14 lockmode => dbms_lock.x_mode,
15 timeout => 0,
16 release_on_commit => TRUE ) = 1 )
17 then
18 raise resource_busy;
19 end if;
20 end;
21 /
Trigger created


I tried the same without using dbms_utility.get_hash_value


rajesh@ORCL> create table t(x number primary key);

Table created.

Elapsed: 00:00:00.40
rajesh@ORCL>
rajesh@ORCL> create or replace trigger t_trig
  2  before insert on T
  3  for each row
  4  declare
  5     l_num number;
  6     resource_busy exception;
  7     pragma exception_init(resource_busy,-54);
  8  begin
  9
 10     if ( dbms_lock.request(
 11                     id => :new.x,
 12                     lockmode => dbms_lock.x_mode,
 13                     timeout =>0,
 14                     release_on_commit=>true
 15                     ) = 1
 16             ) then
 17             raise resource_busy;
 18     end if;
 19  end;
 20  /

Trigger created.

Elapsed: 00:00:00.09
rajesh@ORCL>
rajesh@ORCL> insert into t(x) values (1);

1 row created.

Elapsed: 00:00:00.07
rajesh@ORCL>


And, in the Session-2 I got this

rajesh@ORCL> insert into t(x) values (1);
insert into t(x) values (1)
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
ORA-06512: at "RAJESH.T_TRIG", line 14
ORA-04088: error during execution of trigger 'RAJESH.T_TRIG'


Elapsed: 00:00:00.00
rajesh@ORCL>


Question:

1) Is that dbms_utility.get_hash_value is really needed to get this Non-Blocking fashion?


Tom Kyte
February 01, 2011 - 10:25 am UTC

I wrote in there I used get_hash_value so I would generate at MOST 1024 locks as enqueue resources are a "resource" and a resource you could run out of.

You can generate an infinite number of locks in theory.

That was what I was trying to avoid.

My goal: good concurrency (small chance of a hash collision on different keys) and good resource utilization.

Facing Prob with DBMS_LOCK.SLEEP

Ajay Gupta, May 06, 2011 - 1:32 am UTC

Hi Guys,
I am Ajay here. I have 3 years of exp in Oracle SQL and PL/SQL.
Please let me know solution for my issue.
I am getting error while compiling procedure in which it is used DBMS_LOCK.sleep (600);

Error(102,10): PLS-00201: identifier 'DBMS_LOCK' must be declared.

Tom Kyte
May 06, 2011 - 10:33 am UTC

you have not been granted direct access to dbms_lock, you'll need to have your DBA do that for you:

http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551289900368934430

Clarifications regarding calling sleep in a proc for long hours of sleep

ORAcle devloper, May 25, 2015 - 11:35 am UTC

create procedure my_sleep( SLEEP_TIME IN NUMBER )
as
begin

for i in 1 .. trunc( SLEEP_TIME/600 )
loop
dbms_lock.sleep( 600 );
end loop;
dbms_lock.sleep( SLEEP_TIME-trunc(SLEEP_TIME/600)*600 );

end;
/
------------------------------------
can we use this proc in the answer for even sleep of 6 to 10 hours without any issue?

Sleep in mount

Laurent Schneider, June 12, 2023 - 6:32 am UTC

Hi :)
Just landed there looking for a sleep in mount.

I came up with using my 1980's C64 BASIC skills

for i in 1 to 10 next i


Sleep 5 seconds on your standby

alter session set PLSQL_OPTIMIZE_LEVEL=0;
for i in 1..1e9 loop null; end loop;


Best regards
Laurent

Chris Saxon
June 12, 2023 - 12:45 pm UTC

Thanks for sharing

Sleep in mount

Laurent Schneider, June 12, 2023 - 2:18 pm UTC

or simply DBMS_BACKUP_RESTORE.SLEEP(10) ;-)

Note 1296382.1


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library