<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Radino's blog &#187; Java</title>
	<atom:link href="http://radino.eu/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://radino.eu</link>
	<description>Focusing on interesting SQL and PL/SQL problems</description>
	<lastBuildDate>Thu, 13 Jan 2011 16:22:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>How to implement sleeping</title>
		<link>http://radino.eu/2008/12/25/how-to-implement-sleeping/</link>
		<comments>http://radino.eu/2008/12/25/how-to-implement-sleeping/#comments</comments>
		<pubDate>Thu, 25 Dec 2008 15:12:25 +0000</pubDate>
		<dc:creator>Radoslav Golian</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://radino.eu/?p=7</guid>
		<description><![CDATA[There are few approaches how to implement sleeping in PL/SQL: DBMS_LOCK.SLEEP procedure (precision: hundredths of a second) DBMS_BACKUP_RESTORE.SLEEP (precision: seconds) java.lang.Thread.sleep method mapped by PL/SQL procedure (precision: milliseconds) Autonomous transaction (In fact, this Tanel&#8217;s post inspired me to write this) (precision: seconds) Of course, I belive there are some other aproaches. Using DBMS_LOCK has some [...]]]></description>
			<content:encoded><![CDATA[<p>There are few approaches how to implement sleeping in PL/SQL:</p>
<ol>
<li><a title="DBMS_LOCK.SLEEP" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm#i997212" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm_i997212?referer=');">DBMS_LOCK.SLEEP</a> procedure (precision: hundredths of a second)</li>
<li><a title="Description of DBMS_BACKUP_RESTORE package" href="http://www.psoug.org/reference/dbms_backup_restore.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.psoug.org/reference/dbms_backup_restore.html?referer=');">DBMS_BACKUP_RESTORE.SLEEP</a> (precision: seconds)</li>
<li><a title="Javadoc for " href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#sleep(long)" target="_blank" onclick="pageTracker._trackPageview('/outgoing/java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html_sleep_long?referer=');">java.lang.Thread.sleep</a> method mapped by PL/SQL procedure (precision: milliseconds)</li>
<li><a title="Using autonomous transactions for sleeping" href="http://blog.tanelpoder.com/2008/05/25/using-autonomous-transactions-for-sleeping/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/blog.tanelpoder.com/2008/05/25/using-autonomous-transactions-for-sleeping/?referer=');">Autonomous transaction</a> (In fact, this Tanel&#8217;s post inspired me to write this) (precision: seconds)</li>
</ol>
<p>Of course, I belive there are some other aproaches.</p>
<p>Using <a title="Description of DBMS_LOCK package" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm?referer=');">DBMS_LOCK</a> has some disadvantages. <a title="Description of DBMS_LOCK package" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm?referer=');">DBMS_LOCK</a> is a powerful package. It&#8217;s not granted by default and some DBAs don&#8217;t like grant this package, at all. They have <a title="DBMS_LOCK Security Model" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm#i1002134" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm_i1002134?referer=');">good reason</a>. If you decide to use <a title="Description of DBMS_LOCK package" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm?referer=');">DBMS_LOCK</a> package to implement sleeping, you should use a proxy package and grant this proxy package instead of direct use of <a title="Description of DBMS_LOCK package" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm?referer=');">DBMS_LOCK</a> package:</p>
<pre>
<pre class="brush: sql">
CONNECT / AS SYSDBA
CREATE USER sleep IDENTIFIED BY sleep ACCOUNT LOCK;
GRANT EXECUTE ON dbms_lock TO sleep;

CREATE OR REPLACE PACKAGE sleep.dbms_lock IS
 PROCEDURE sleep (seconds  IN NUMBER);
END dbms_lock;
/

CREATE OR REPLACE PACKAGE BODY sleep.dbms_lock IS
  PROCEDURE sleep (seconds  IN NUMBER) IS
  BEGIN
    sys.dbms_lock.sleep(seconds); -- do NOT forget sys prefix to avoid recursion!
  END sleep;
END dbms_lock;
/

CREATE USER test IDENTIFIED BY test;
GRANT CREATE SESSION TO test;
GRANT EXECUTE ON sleep.dbms_lock TO test;
GRANT CREATE SYNONYM TO test;

CONNECT test/test

CREATE OR REPLACE SYNONYM dbms_lock FOR sleep.dbms_lock;

SET TIMING ON
EXECUTE dbms_lock.sleep(1);
</pre>
</pre>
<p>You should be also aware of <a title="Link to metalink bug description" href="https://metalink.oracle.com/metalink/plsql/showdoc?db=Bug&amp;id=1842189" target="_blank" onclick="pageTracker._trackPageview('/outgoing/metalink.oracle.com/metalink/plsql/showdoc?db=Bug_amp_id=1842189&amp;referer=');">Bug 1842189</a> (Link requires access to Metalink): <a title="DBMS_LOCK.SLEEP" href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm#i997212" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_lock.htm_i997212?referer=');">DBMS_LOCK.SLEEP</a> does not provide the right sleep interval when sleep duration is more than 3600 seconds. According Metalink this bug is reproducing from 8.1.6 through 11.1.0.6.</p>
<p>Here is a test case:</p>
<pre>
<pre class="brush: sql">
CONNECT / AS sysdba

BEGIN
  dbms_output.put_line(&#039;before sleep: &#039;||to_char(SYSDATE,&#039;DD.MM.YYYY HH24:MI:SS&#039;));
  dbms_lock.sleep(6000);
  dbms_output.put_line(&#039;after sleep : &#039;||to_char(SYSDATE,&#039;DD.MM.YYYY HH24:MI:SS&#039;));
END;
/
</pre>
</pre>
<p>I tested it on various versions, but I encounter this bug only on 9.2.0.8.0:</p>
<p>9.2.0.8.0 on Red Hat 9 (28 minutes and 25 seconds elapsed)</p>
<pre>before sleep: 04.10.2008 22:29:35
after sleep : 04.10.2008 22:58:00

PL/SQL procedure successfully completed.</pre>
<p>10.2.0.1.0 on CentOS (100 minutes elapsed &#8211; bug didn&#8217;t appear)</p>
<pre>before sleep: 05.10.2008 20:17:08
after sleep : 05.10.2008 21:57:08

PL/SQL procedure successfully completed.</pre>
<p>10.2.0.4.0 on CentOS (100 minutes elapsed &#8211; bug didn&#8217;t appear)</p>
<pre>before sleep: 04.10.2008 22:58:00
after sleep : 05.10.2008 00:38:00

PL/SQL procedure successfully completed.</pre>
<p>11.1.0.6.0 on CentOS (100 minutes elapsed &#8211; bug didn&#8217;t appear):</p>
<pre>before sleep: 04.10.2008 22:24:53
after sleep : 05.10.2008 00:04:53

PL/SQL procedure successfully completed.</pre>
<p>However, you should test it out on your environment, if you require such long sleeping intervals.</p>
<p>A valid workaround is to use <a title="Description of DBMS_BACKUP_RESTORE package" href="http://www.psoug.org/reference/dbms_backup_restore.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.psoug.org/reference/dbms_backup_restore.html?referer=');">DBMS_BACKUP_RESTORE</a> package. Procedure DBMS_BACKUP_RESTORE.SLEEP gives the expected amount of sleep even if the time interval is more than 3600 seconds. But <a title="Description of DBMS_BACKUP_RESTORE package" href="http://www.psoug.org/reference/dbms_backup_restore.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.psoug.org/reference/dbms_backup_restore.html?referer=');">SYS.DBMS_BACKUP_RESTORE</a> is also very powerful (you should use proxy package) and it is undocumented, so probably for internal use only (RMAN uses it).</p>
<p>I like approach using <a title="Javadoc for " href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#sleep(long)" target="_blank" onclick="pageTracker._trackPageview('/outgoing/java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html_sleep_long?referer=');">java.lang.Thread.sleep</a> method mapped by PL/SQL procedure. But you have to have Java installed on your database to implement this.</p>
<pre>
<pre class="brush: sql">
CREATE OR REPLACE PROCEDURE sleep(x_millis IN NUMBER) AS LANGUAGE JAVA
NAME &#039;java.lang.Thread.sleep(int)&#039;;
/
SET TIMING ON
EXECUTE sleep(10000);
</pre>
</pre>
<p>You should by also aware of some difficulties with <a title="Terminating sessions" href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/manproc008.htm" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/server.111/b28310/manproc008.htm?referer=');">killing</a> sleeping sessions. A sleeping session is an active session. When you issue an <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_2013.htm#BABEBJFA" target="_blank" onclick="pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_2013.htm_BABEBJFA?referer=');">ALTER SYSTEM KILL SESSION</a> command on this session, it is not killed until it awakes from sleep.  On Unix-like operating systems, you can kill <span class="vcb_rt">corresponding </span>OS process with <a title="Kill command" href="http://en.wikipedia.org/wiki/Kill_(Unix)" target="_blank" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Kill_Unix?referer=');">kill command</a>. On Windows, you can kill <span class="vcb_rt">corresponding thread of oracle process </span> with <a title="Orakill example" href="http://www.oracle.com/technology/oramag/code/tips2003/030903.html" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.oracle.com/technology/oramag/code/tips2003/030903.html?referer=');">orakill command</a>.</p>
<p>I will demonstrate this on a simple example. In the first session, I will run this script, which will sleep for 100 seconds:</p>
<pre>
<pre class="brush: sql">
select to_char(sysdate,&#039;hh24:mi:ss&#039;) start_time from dual;

set timing on
begin
  dbms_application_info.set_module(&#039;sleep&#039;, &#039;sleep&#039;);
  sleep(x_millis =&gt; 100000);
end;
/
</pre>
</pre>
<p>Immediately, in the second session, I will try to kill the first sleeping session with the ALTER SYSTEM command. This command will wait up to 60 seconds for the sleeping session to be terminated, but then I will receive a message indicating that the sleeping session has been only marked to be terminated and this session will continue to sleep. After 100 seconds, when it awakes, it will be terminated.</p>
<pre>
<pre class="brush: sql">
select to_char(sysdate, &#039;hh24:mi:ss&#039;) start_time from dual;

set linesize 120
column sid new_value sid
column serial new_value serial
column status format a8

select to_char(s.sid) sid, to_char(s.serial#) serial, s.status, p.spid
from v$session s, v$process p
where s.action = &#039;sleep&#039;
and s.STATUS &lt;&gt; &#039;KILLED&#039;
and s.paddr = p.addr(+);

set timing on
alter system kill session &#039;&amp;sid, &amp;serial&#039; immediate;

set timing off
select s.sid, s.serial#, s.status, p.spid
from v$session s, v$process p
where s.action = &#039;sleep&#039;
and s.paddr = p.addr(+);
</pre>
</pre>
<p>Output of the first session:</p>
<pre>START_TI
--------
15:24:29
PL/SQL procedure successfully completed.
Elapsed: 00:01:40.84
</pre>
<p>We can see that it takes 100 seconds, even we tried to kill it.</p>
<p>Output of the second session:</p>
<pre>START_TI
--------
15:24:34

SID                                      SERIAL                                   STATUS   SPID
---------------------------------------- ---------------------------------------- -------- ------------
48                                       2782                                     ACTIVE   11267

old   1: alter system kill session '&amp;sid, &amp;serial' immediate
new   1: alter system kill session '48, 2782' immediate
alter system kill session '48, 2782' immediate
*
ERROR at line 1:
ORA-00031: session marked for kill

Elapsed: 00:01:01.80

       SID    SERIAL# STATUS   SPID
---------- ---------- -------- ------------
        48       2782 KILLED   11267<br class="spacer_" /></pre>
<p>Note: The value in the SPID column could be used for the kill or the orakill command to kill the sleeping session on the OS level.</p>
]]></content:encoded>
			<wfw:commentRss>http://radino.eu/2008/12/25/how-to-implement-sleeping/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

