<?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>remidian.com &#187; DBA util</title>
	<atom:link href="http://remidian.com/category/oracle/dba-util/feed" rel="self" type="application/rss+xml" />
	<link>http://remidian.com</link>
	<description>Braindumps of Remi Visser, freelance Oracle DBA.</description>
	<lastBuildDate>Mon, 10 May 2010 12:33:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Batch SQL statements in parallel (multiple) sessions</title>
		<link>http://remidian.com/oracle/dba-util/batch-sql-in-parallel.html</link>
		<comments>http://remidian.com/oracle/dba-util/batch-sql-in-parallel.html#comments</comments>
		<pubDate>Fri, 18 Jan 2008 17:39:58 +0000</pubDate>
		<dc:creator>remivisser</dc:creator>
				<category><![CDATA[DBA util]]></category>

		<guid isPermaLink="false">http://remidian.com/oracle/dba-util/batch-sql-in-parallel.html</guid>
		<description><![CDATA[So it was decided &#8216;this batch&#8217; had to be done &#8216;this weekend&#8217;. Thousands of SQL statements some of them would take minutes others hours&#8230; And MAKE SURE it&#8217;s finished monday. I hate babysitting multiple sessions having to create multiple SQL Scripts to spread the workload (it&#8217;s on a 20+ CPUS&#8217;s database server) So I wrote [...]]]></description>
			<content:encoded><![CDATA[<p>So it was decided &#8216;this batch&#8217; had to be done &#8216;this weekend&#8217;. Thousands of SQL statements some of them would take minutes others hours&#8230; And MAKE SURE it&#8217;s finished monday.<span id="more-68"></span>
<p>
I hate babysitting <em>multiple</em> sessions having to create <em>multiple</em> SQL Scripts to spread the workload (it&#8217;s on a 20+ CPUS&#8217;s database server) So I wrote this PL/SQL &#8216;application&#8217; in a hurry to enable starting multiple databases sessions in <code>nohup</code>, each session picks up the next SQL statement &#8216;available&#8217; (WHERE endtime IS NULL). It will save me some sleep.
</p>
<h3>Setup</h3>
<h6>The table holding my SQL statements</h6>
<pre>
CREATE TABLE batchsql
 ( batchid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(64)&nbsp;&nbsp;&nbsp;&nbsp;NOT NULL
 , sqlid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NOT NULL UNIQUE
 , sqltext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varchar2(4000)&nbsp;&nbsp;NOT NULL
 , starttime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATE
 , endtime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATE
 , sqlcode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTEGER
 , sqlerrm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(256)
 , error_stack&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(4000)
 , error_backtrace&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(4000)
 );
</pre>
<p><em>would be nicer to make the &#8216;sqlid&#8217; column a compisone unique key with the batchid (harmless off course).</em></p>
<h6>The anonymous PL/SQL block that will loop and execute these statements</h6>
<pre>
DECLARE
&nbsp;&nbsp;v_batchid&nbsp;&nbsp;batchsql.batchid%TYPE;
&nbsp;&nbsp;i_sqlid&nbsp;&nbsp;&nbsp;&nbsp;batchsql.sqlid%TYPE;
&nbsp;&nbsp;v_sqltext&nbsp;&nbsp;batchsql.sqltext%TYPE;
&nbsp;
&nbsp;&nbsp;i_sqlcode&nbsp;&nbsp;PLS_INTEGER;
&nbsp;&nbsp;v_sqlerrm&nbsp;&nbsp;VARCHAR2(256);
&nbsp;
&nbsp;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PLS_INTEGER;
&nbsp;
BEGIN
&nbsp;
<strong>&nbsp;&nbsp;v_batchid := &#039;DB01_ANALYZE_20080118&#039;;</strong>
&nbsp;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; := 0;
&nbsp;
&nbsp;&nbsp;LOOP
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#45;- get statement that nobody is working on
&nbsp;&nbsp;&nbsp;&nbsp;SELECT sqlid,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sqltext
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTO i_sqlid,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v_sqltext
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM batchsql
&nbsp;&nbsp;&nbsp;&nbsp; WHERE batchid = v_batchid
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND starttime IS NULL
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND rownum = 1;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;i := i +1;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#45;- open new block for &#039;sqltext&#039; statement
&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- first set the starttime, (lock statement) to make sure 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- no other session will pick up the same statement
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET starttime = SYSDATE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- execute the statement
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXECUTE IMMEDIATE v_sqltext;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- everything went well, register endtime and commit
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET endtime = SYSDATE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHEN OTHERS THEN
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- error occured, register endtime and errors
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i_sqlcode := SQLCODE;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v_sqlerrm := SQLERRM;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET endtime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= SYSDATE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , sqlcode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= i_sqlcode
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , sqlerrm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= v_sqlerrm
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , error_stack&nbsp;&nbsp;= DBMS_UTILITY.FORMAT_ERROR_STACK()
&#45;- Uncomment &#039;FORMAT_ERROR_BACKTRACE()&#039; for pre 10G
&#45;- , error_backtrace = DBMS_UTILITY.FORMAT_ERROR_BACKTRACE()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
&nbsp;&nbsp;&nbsp;&nbsp;END;
&nbsp;
&nbsp;&nbsp;END LOOP;
&nbsp;
EXCEPTION
&nbsp;&nbsp;WHEN NO_DATA_FOUND THEN
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;IF i = 0 THEN
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;No SQL Statements found for batch &#039;&#039;&#039; || v_batchid || &#039;&#039;&#039;&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;ELSE
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;Carried out &#039; || TO_CHAR(i) || &#039; SQL statements&#039;);
&nbsp;&nbsp;&nbsp;&nbsp;END IF;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;Time is &#039;&#039;&#039; || to_CHAR(SYSDATE, &#039;DD-MON-YY hh24:mi:ss&#039;) || &#039;&#039;&#039;&#039;);
&nbsp;
END;
/
&nbsp;
</pre>
<h3>Example</h3>
<p>
Suppose I have to analyze a bunch of tables, I will first have to fill my &#8216;batchsql&#8217; table with all the SQL Statements that belong to this batch, I identify the batch to &#8216;DB01_ANALYZE_20080118&#8242;.
</p>
<h6>Generate some SQL statements and insert them in the batchsql table</h6>
<pre>
SQL&gt; DEFINE BATCHID&nbsp;&nbsp;= &quot;&#039;&#039;DB01_ANALYZE_20080118&#039;&#039;&quot;
SQL&gt; DEFINE QUOTE&nbsp;&nbsp;&nbsp;&nbsp;= &quot;&#039;&#039;&quot;
SQL&gt; SELECT &#039;INSERT INTO batchsql 
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( batchid, sqlid, sqltext)
&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUES
&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( &amp;BATCHID,&#039; || ROWNUM || &#039;, &amp;QUOTE.ANALYZE TABLE &#039; || table_name || &#039; COMPUTE STATISTICS&amp;QUOTE);&#039;
&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp; FROM user_tables
&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;WHERE rownum &lt; 5
&nbsp;&nbsp;7&nbsp;&nbsp;/
&#039;INSERTINTOBATCHSQL(BATCHID,SQLID,SQLTEXT)VALUES(&#039;&#039;DB01_ANALYZE_20080118&#039;&#039;,&#039;||ROWNUM||&#039;,&#039;&#039;ANALYZETABLE&#039;||TABLE_
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-
INSERT INTO batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( batchid, sqlid, sqltext)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUES
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( &#039;DB01_ANALYZE_20080118&#039;,1, &#039;ANALYZE TABLE BATCHSQL COMPUTE STATISTICS&#039;);
&nbsp;
INSERT INTO batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( batchid, sqlid, sqltext)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VALUES
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( &#039;DB01_ANALYZE_20080118&#039;,2, &#039;ANALYZE TABLE DEMO COMPUTE STATISTICS&#039;);
&nbsp;
SQL&gt; 
</pre>
<p>
Do test the error handling I insert one bogus statement that will generate an error.
</p>
<pre>
SQL&gt; INSERT INTO batchsql
&nbsp;&nbsp;2&nbsp;&nbsp; ( batchid, sqlid, sqltext)
&nbsp;&nbsp;3&nbsp;&nbsp; VALUES
&nbsp;&nbsp;4&nbsp;&nbsp; ( &#039;DB01_ANALYZE_20080118&#039;, 5, &#039;HELLO WORLD!&#039;);
&nbsp;
1 row created.
&nbsp;
SQL&gt; 
SQL&gt; 
</pre>
<p>
Now look at the contents of the batchsql table, we see three statements for the &#8216;DB01_ANALYZE_20080118&#8242; batch.
</p>
<pre>
SQL&gt; select batchid, sqlid, sqltext, starttime, endtime, sqlcode, sqlerrm from batchsql;
BATCHID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQLID SQLTEXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STARTTIME ENDTIME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQLCODE SQLERRM
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 HELLO WORLD!
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 ANALYZE TABLE BATCHSQL COMPUTE STATISTICS
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 ANALYZE TABLE DEMO COMPUTE STATISTICS
&nbsp;
SQL&gt; 
</pre>
<p>Start a session that will start executing statements found in the batchsql table for batch &#8216;DB01_ANALYZE_20080118&#8242;:</p>
<pre>
SQL&gt; ed
Wrote file afiedt.buf
&nbsp;
&nbsp;&nbsp;1&nbsp;&nbsp;DECLARE
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;v_batchid&nbsp;&nbsp;batchsql.batchid%TYPE;
&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;i_sqlid&nbsp;&nbsp;&nbsp;&nbsp;batchsql.sqlid%TYPE;
&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;v_sqltext&nbsp;&nbsp;batchsql.sqltext%TYPE;
&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;i_sqlcode&nbsp;&nbsp;PLS_INTEGER;
&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;v_sqlerrm&nbsp;&nbsp;VARCHAR2(256);
&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PLS_INTEGER;
&nbsp;&nbsp;8&nbsp;&nbsp;BEGIN
&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;v_batchid := &#039;DB01_ANALYZE_20080118&#039;;
 10&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp; := 0;
 11&nbsp;&nbsp;&nbsp;&nbsp;LOOP
 12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- get statement that nobody is working on
 13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SELECT sqlid,
 14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sqltext
 15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTO i_sqlid,
 16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v_sqltext
 17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FROM batchsql
 18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE batchid = v_batchid
 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND starttime IS NULL
 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND rownum = 1;
 21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i := i +1;
 22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- open new block for &#039;sqltext&#039; statement
 23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BEGIN
 24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- first set the starttime, (lock statement) to make sure
 25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- no other session will pick up the same statement
 26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
 27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET starttime = SYSDATE
 28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
 29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
 30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- execute the statement
 31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXECUTE IMMEDIATE v_sqltext;
 32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- everything went well, register endtime and commit
 33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
 34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET endtime = SYSDATE
 35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
 36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
 37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXCEPTION
 38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WHEN OTHERS THEN
 39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#45;- error occured, register endtime and errors
 40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i_sqlcode := SQLCODE;
 41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v_sqlerrm := SQLERRM;
 42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPDATE batchsql
 43&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET endtime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= SYSDATE
 44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , sqlcode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= i_sqlcode
 45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , sqlerrm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= v_sqlerrm
 46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , error_stack&nbsp;&nbsp;= DBMS_UTILITY.FORMAT_ERROR_STACK()
 47&nbsp;&nbsp;&#45;- Uncomment &#039;FORMAT_ERROR_BACKTRACE()&#039; for pre 10G
 48&nbsp;&nbsp;&#45;- , error_backtrace = DBMS_UTILITY.FORMAT_ERROR_BACKTRACE()
 49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE sqlid = i_sqlid;
 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COMMIT;
 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END;
 52&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;
 53&nbsp;&nbsp;EXCEPTION
 54&nbsp;&nbsp;&nbsp;&nbsp;WHEN NO_DATA_FOUND THEN
 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IF i = 0 THEN
 56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;No SQL Statements found for batch &#039;&#039;&#039; || v_batchid || &#039;&#039;&#039;&#039;);
 57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ELSE
 58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;Carried out &#039; || TO_CHAR(i) || &#039; SQL statements&#039;);
 59&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END IF;
 60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DBMS_OUTPUT.PUT_LINE ( &#039;Time is &#039;&#039;&#039; || to_CHAR(SYSDATE, &#039;DD-MON-YY hh24:mi:ss&#039;) || &#039;&#039;&#039;&#039;);
 61* END;
 62&nbsp;&nbsp;/
Carried out 3 SQL statements
Time is &#039;18-JAN-08 18:37:01&#039;
&nbsp;
PL/SQL procedure successfully completed.
&nbsp;
SQL&gt; REM and again
SQL&gt; /
No SQL Statements found for batch &#039;DB01_ANALYZE_20080118&#039;
Time is &#039;18-JAN-08 18:37:20&#039;
&nbsp;
PL/SQL procedure successfully completed.
&nbsp;
SQL&gt; 
SQL&gt; 
</pre>
<p>
Pretty straigh forward, not?
</p>
<ul>
<li>The first run the starttime column is NULL (for every row),</li>
<li>The statements are executed, both the starttime and the endtime are updated at every single execution</li>
<li>The second run find no rows where starttime IS NULL and will not execute any statement at all.</li>
</ul>
<p>
See the log results.
</p>
<pre>
SQL&gt; select batchid, sqlid, sqltext, starttime, endtime, sqlcode, sqlerrm from batchsql;
BATCHID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQLID SQLTEXT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STARTTIME ENDTIME&nbsp;&nbsp; SQLCODE SQLERRM
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 HELLO WORLD!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 18-JAN-08 18-JAN-08&nbsp;&nbsp;&nbsp;&nbsp;-900 ORA-00900: invalid S
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QL statement
&nbsp;
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1 ANALYZE TABLE BATCHSQL COMPUTE STATISTICS&nbsp;&nbsp;18-JAN-08 18-JAN-08
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2 ANALYZE TABLE DEMO COMPUTE STATISTICS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;18-JAN-08 18-JAN-08
&nbsp;
SQL&gt; 
</pre>
<p>
Of course, you can add extra functionalities as many as you would like, store the sessionid for every SQL statement, have multiple runs for a batch to reuse statements, etc etc. Oh and of course I should rewrite it to a SQL Procedure or Package.
</p>
<p>
The babysitting is now minimized to running this query:
</p>
<pre>
&nbsp;
col batch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for 9999
col completed&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for 9999
col todo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for 9999
col activesessions&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for 9999999&nbsp;&nbsp;&nbsp;&nbsp; head &quot;ACTIVE|SESSIONS&quot;
col errors&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for 99999
col elapsed_seconds&nbsp;&nbsp;&nbsp;&nbsp; for 9999999&nbsp;&nbsp;&nbsp;&nbsp; head &quot;ELAPSED|SECONDS&quot;
col avg_execution_time&nbsp;&nbsp;for 9999999&nbsp;&nbsp;&nbsp;&nbsp; head &quot;AVG|EXECUTION|TIME&quot;
col percentage_complete for 9999999&nbsp;&nbsp;&nbsp;&nbsp; head &quot;PERCENTAGE|COMPLETE&quot;
&nbsp;
&#45;- as I only have one batch loaded I don&#039;t need to filter on the batchid
select batch.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;batch,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; completed.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;completed,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; batch.c - completed.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;todo,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; to_char( times.started, &#039;DD-MM-HH hh24:mi&#039;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;started,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; to_char( times.lastcompleted, &#039;DD-MM-HH hh24:mi&#039;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastcompleted,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; round( completed.c / batch.c * 100, 1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; percentage_complete,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; activesessions.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; activesessions,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errors,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( sysdate - times.started) *24*60*60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elapsed_seconds,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trunc( ( sysdate - times.started)*24*60*60 / completed.c)&nbsp;&nbsp;avg_execution_time,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; to_char( sysdate +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( batch.c - completed.c) *
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( (sysdate - times.started) / completed.c)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , &#039;DD-MM-HH hh24:mi&#039;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;est_end_time
 from ( select count(*) as c from batchsql )&nbsp;&nbsp;&nbsp;&nbsp;batch
&nbsp;&nbsp;&nbsp;&nbsp;, ( select count(*) as c from batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where endtime is not null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; completed
&nbsp;&nbsp;&nbsp;&nbsp;, ( select count(*) as c
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where starttime is not null
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and endtime is null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; activesessions
&nbsp;&nbsp;&nbsp;&nbsp;, ( select count(*) as c
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from batchsql
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where sqlcode is not null )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;errors
&nbsp;&nbsp; , ( select min(starttime) started,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max(starttime) lastcompleted
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from batchsql )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; times
/
&nbsp;
</pre>
<pre>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AVG
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PERCENTAGE&nbsp;&nbsp; ACTIVE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELAPSED EXECUTION
BATCH COMPLETED&nbsp;&nbsp;TODO STARTED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LASTCOMPLETED&nbsp;&nbsp;&nbsp;&nbsp;COMPLETE SESSIONS ERRORS&nbsp;&nbsp;SECONDS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIME EST_END_TIME
&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
 1524&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 492&nbsp;&nbsp;1032 18-01-06 18:45 18-01-10 22:01&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;11756&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;23 19-01-04 04:52
&nbsp;
SQL&gt; 
SQL&gt; 
SQL&gt; select*from batchsql where sqlcode is not null;
BATCHID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQLID
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-
SQLTEXT
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
STARTTIME&nbsp;&nbsp;ENDTIME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQLCODE SQLERRM
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
ERROR_STACK
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
ERROR_BACKTRACE
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
DB01_ANALYZE_20080118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;84
ANALYZE TABLE ********
18-01-2008 18-01-2008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-1555 ORA-01555: snapshot too old: rollback segment number 2 with name &quot;_SYSSMU2$&quot; too small
ORA-01555: snapshot too old: rollback segment number 2 with name &quot;_SYSSMU2$&quot; too small
&nbsp;
SQL&gt; 
&nbsp;
</pre>
<h3>UPDATE 2010-05-10T11:04:21+00:00</h3>
<p>
Make sqlid non unique and add trigger to generate sqlid&#8217;s.
</p>
<pre>
CREATE TABLE batchsql
 ( batchid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(64)&nbsp;&nbsp;&nbsp;&nbsp;NOT NULL
 , sqlid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTEGER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NOT NULL
 , sqltext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varchar2(4000)&nbsp;&nbsp;NOT NULL
 , starttime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATE
 , endtime&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATE
 , sqlcode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INTEGER
 , sqlerrm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(256)
 , error_stack&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(4000)
 , error_backtrace&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARCHAR2(4000)
 );
&nbsp;
CREATE SEQUENCE s_batchsql;
&nbsp;
CREATE OR REPLACE TRIGGER t_batchsql
BEFORE INSERT ON batchsql
FOR EACH ROW
WHEN (new.sqlid IS NULL)
BEGIN
&nbsp;&nbsp;SELECT s_batchsql.NEXTVAL
&nbsp;&nbsp;INTO&nbsp;&nbsp; :new.sqlid
&nbsp;&nbsp;FROM&nbsp;&nbsp; dual;
END;
/
</pre>
<p>
Create script to execute statements from batch table
</p>
<pre>
export ORAENV_ASK=NO;
export ORACLE_SID=sfsse001;
/usr/local/bin/oraenv
&nbsp;
sqlplus -silent &#039;/ as sysdba&#039; &lt;&lt;EOF
&nbsp;
column d new_value d
select to_char( sysdate, &#039;YYYYMMDD-HH24MISS&#039;) d from dual;
&nbsp;
set serveroutput on
&nbsp;
spool batch_&amp;d.log
&nbsp;
@r.sql
&nbsp;
spool off
&nbsp;
EOF
&nbsp;
</pre>
<pre>
$ nohup r.sh &amp;
&nbsp;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://remidian.com/oracle/dba-util/batch-sql-in-parallel.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dba$log_blocker</title>
		<link>http://remidian.com/oracle/dba-util/dbalog_blocker.html</link>
		<comments>http://remidian.com/oracle/dba-util/dbalog_blocker.html#comments</comments>
		<pubDate>Tue, 27 Jun 2006 05:55:00 +0000</pubDate>
		<dc:creator>remivisser</dc:creator>
				<category><![CDATA[DBA util]]></category>

		<guid isPermaLink="false">http://remidian.com/oracle/dbalog_blocker.html</guid>
		<description><![CDATA[Code below will save the information of the &#8216;blocking session&#8217; in an ORA-00060 situation. Since both sessions are equally guilty of the deadlock Oracle picks one session at random to get the ORA-00060, the update will fail for this session and a trace file is written to the user_dump_dest. In this trace file you can [...]]]></description>
			<content:encoded><![CDATA[<p>
Code below will save the information of the &#8216;blocking session&#8217; in an ORA-00060 situation. <span id="more-3"></span>
</p>
<p>
Since both sessions are equally guilty of the deadlock Oracle picks one session at random to get the ORA-00060, the update will fail for this session and a trace file is written to the user_dump_dest. In this trace file you can find the current SQL statement of the session that got the ORA-00060 and the os pids of the sessions on the server, however there is not as much information as to the session that &#8217;caused the deadlock&#8217; as you might want to see.
</p>
<p>
The &#8216;servererror&#8217; triggers (around since 8i), enable you to write a trigger and storing some usefull information for later analysis.
</p>
<p>
Please note the triggers firing on the &#8216;servererror&#8217; start a separate transaction and commits it after firing the trigger. No need to start an autonomous transaction, since it already is so to say, see <a href="http://download-uk.oracle.com/docs/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm#CHDHFBBG">Database Application Developer&#8217;s Guide &#8211; Fundamentals &#8211; 9 Coding Triggers &#8211; Table 9-3 System Manager Events</a>.
</p>
<h3>tables</h3>
<p>
Create some tables to hold the information I&#8217;m interested in.
</p>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; create table log$event
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; ( event#&nbsp;&nbsp;&nbsp;&nbsp; number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; constraint pk_log$event primary key
&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp; , event&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varchar2(512)
&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp; , eventtime&nbsp;&nbsp;date
&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp; )
&nbsp;&nbsp;6&nbsp;&nbsp;/
&nbsp;
Table created.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; create table log$session
&nbsp;&nbsp;2&nbsp;&nbsp;as
&nbsp;&nbsp;3&nbsp;&nbsp;select 1 event#
&nbsp;&nbsp;4&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.*
&nbsp;&nbsp;5&nbsp;&nbsp;from&nbsp;&nbsp; v$session&nbsp;&nbsp;&nbsp;&nbsp;s
&nbsp;&nbsp;6&nbsp;&nbsp;where&nbsp;&nbsp;1 = 2
&nbsp;&nbsp;7&nbsp;&nbsp;/
&nbsp;
Table created.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; create table log$session_longops
&nbsp;&nbsp;2&nbsp;&nbsp;as
&nbsp;&nbsp;3&nbsp;&nbsp;select 1 event#
&nbsp;&nbsp;4&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.*
&nbsp;&nbsp;5&nbsp;&nbsp;from&nbsp;&nbsp; v$session_longops s
&nbsp;&nbsp;6&nbsp;&nbsp;where&nbsp;&nbsp;1 = 2
&nbsp;&nbsp;7&nbsp;&nbsp;/
&nbsp;
Table created.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; create table log$sqltext_with_newlines
&nbsp;&nbsp;2&nbsp;&nbsp;as
&nbsp;&nbsp;3&nbsp;&nbsp;select 1 event#
&nbsp;&nbsp;4&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.*
&nbsp;&nbsp;5&nbsp;&nbsp;from&nbsp;&nbsp; v$sqltext_with_newlines&nbsp;&nbsp;&nbsp;&nbsp;s
&nbsp;&nbsp;6&nbsp;&nbsp;where&nbsp;&nbsp;1 = 2
&nbsp;&nbsp;7&nbsp;&nbsp;/
&nbsp;
Table created.
&nbsp;
</pre>
<p>
Some constraints;
</p>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; alter table log$session 
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; add constraint fk_log$session foreign key (event#) references log$event;
&nbsp;
Table altered.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; alter table log$session_longops
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; add constraint fk_log$session_longops foreign key (event#) references log$event;
&nbsp;
Table altered.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; alter table log$sqltext_with_newlines
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; add constraint fk_log$sqltext_with_newlines foreign key (event#) references log$event;
&nbsp;
Table altered.
&nbsp;
</pre>
<h3>servererror trigger</h3>
<p>
The servererror trigger, firing after every servererror;
</p>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; grant administer database trigger to remi
&nbsp;&nbsp;2&nbsp;&nbsp;/
&nbsp;
Grant succeeded.
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; create or replace trigger log$ora00060
&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp; after servererror on database
&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;4&nbsp;&nbsp;declare
&nbsp;&nbsp;5&nbsp;&nbsp;
&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp; n_event#&nbsp;&nbsp;pls_integer;
&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp; d_date&nbsp;&nbsp;&nbsp;&nbsp;date;
&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp; n_blocked pls_integer;
 10&nbsp;&nbsp;&nbsp;&nbsp; n_blocker pls_integer;
 11&nbsp;&nbsp;&nbsp;&nbsp; 
 12&nbsp;&nbsp;begin
 13&nbsp;&nbsp;&nbsp;&nbsp; 
 14&nbsp;&nbsp;&nbsp;&nbsp; n_event# := sys.dbms_utility.get_time;
 15&nbsp;&nbsp;&nbsp;&nbsp; d_date&nbsp;&nbsp; := sysdate;
 16&nbsp;&nbsp;&nbsp;&nbsp; 
 17&nbsp;&nbsp;&nbsp;&nbsp; if is_servererror(60) then
 18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into log$event 
 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( event#
 21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , event
 22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , eventtime 
 23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )
 24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; values
 25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( n_event#
 26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , &#039;ORA-00060: deadlock detected while waiting for resource&#039;
 27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , d_date
 28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );
 29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
 30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
 32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* retieve sid of blocked/blocking session
 33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
 34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select sid
 35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;into&nbsp;&nbsp; n_blocked
 36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$mystat
 37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;rownum = 1;
 38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 39&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select sid
 40&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;into&nbsp;&nbsp; n_blocker
 41&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$lock
 42&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;request &gt; 0
 43&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;&nbsp;&nbsp;&nbsp;(id1, id2) in (
 44&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select id1
 45&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id2
 46&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from&nbsp;&nbsp; v$lock
 47&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where&nbsp;&nbsp;block = 1
 48&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp;sid = n_blocked
 49&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );
 50&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 51&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
 52&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* store information
 53&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 54&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into log$session
 55&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select n_event#
 56&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.*
 57&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$session s
 58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;sid in ( n_blocked, n_blocker);
 59&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 60&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into log$sqltext_with_newlines
 61&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select n_event#
 62&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.*
 63&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$sqltext_with_newlines v
 64&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;address in (
 65&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select sql_address
 66&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$session
 67&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;sid in ( n_blocker)
 68&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;union
 69&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select prev_sql_addr
 70&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$session
 71&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;sid in ( n_blocker)
 72&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);
 73&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 74&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into log$session_longops
 75&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select n_event#
 76&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.*
 77&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;&nbsp; v$session_longops v
 78&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;&nbsp;sid = n_blocker;
 79&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 80&nbsp;&nbsp;&nbsp;&nbsp; end if; &#45;- if is_servererror(60) then
 81&nbsp;&nbsp;
 82&nbsp;&nbsp;exception 
 83&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when others then
 84&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; null;
 85&nbsp;&nbsp;end;
 86&nbsp;&nbsp;/
&nbsp;
Trigger created.
&nbsp;
</pre>
<h3>Live example</h3>
<p>
The scenario below demostrates the behaviour the trigger above.
</p>
<h6>Session one</h6>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; select * from demo;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; K
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
[REMI@DB01.REMIDIAN.COM]
SQL&gt; update demo set k = 1 where k = 1;
&nbsp;
1 row updated.
</pre>
<h6>Session two</h6>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; update demo set k = 2 where k = 2;
&nbsp;
1 row updated.
</pre>
<h6>Back to session one</h6>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; update demo set k = 2 where k = 2;
&nbsp;
1 row updated.
&nbsp;
</pre>
<h6>And finally in session two</h6>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt;&nbsp;&nbsp;update demo set k = 1 where k = 1; 
 update demo set k = 1 where k = 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
&nbsp;
</pre>
<h6>Retrieve the logged results containing information about the deadlock event and the involved sessions.</h6>
<pre>
[REMI@DB01.REMIDIAN.COM]
SQL&gt; select * from log$event;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;EVENT# EVENT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EVENTTIME
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-
-821696669 ORA-00060: deadlock detected while waiting for resource&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;27-JUN-06
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; select event#, sid, osuser, lockwait, last_call_et, status from log$session;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;EVENT#&nbsp;&nbsp;&nbsp;&nbsp; SID OSUSER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LOCKWAIT LAST_CALL_ET STATUS
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;--
-821696669&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15 REMIVISSER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 801E9EFC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 ACTIVE
-821696669&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;86 REMIVISSER&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 ACTIVE
&nbsp;
[REMI@DB01.REMIDIAN.COM]
SQL&gt; select * from log$sqltext_with_newlines;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;EVENT# ADDRESS&nbsp;&nbsp;HASH_VALUE COMMAND_TYPE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PIECE SQL_TEXT
&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;&#45;-- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;&#45;- &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--
-821696669 80B70B44 3948528108&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;update demo set k = 1 where k = 1
&nbsp;
</pre>
<h3>10g NOTE</h3>
<p>
Code will NOT work in Oracle 10G (creation of log$session table as select * from v$session fails because in 10G the v$session view also has a column event#). But in 10G the tracefile generated upon ORA-00060 errors has a lot more informatin about the &#8216;blocking&#8217; session in an ORA-00060 situation. If you still want this to work in 10G simply change the &#8216;event#&#8217; column to have another name.
</p>
<p></ins></p>
]]></content:encoded>
			<wfw:commentRss>http://remidian.com/oracle/dba-util/dbalog_blocker.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
