Reputation: 2041
Lets say a user is running a huge PL/SQL script, consisting of 2000 lines, and somewhere in there, there's a statement that is "waiting" for some condition to become true. For that a construction like this example is used:
BEGIN
--Wail until 2 o clock
WHILE (to_date('06-01-2014 02:00','dd-mm-yyyy hh24:mi') > sysdate)
LOOP
DBMS_LOCK.SLEEP(60);
END LOOP;
--code to execute after 2 o clock
END;
Now there are several constructions of this kind in the script, and the script seems to be running forever, so the user asked me where it's at. The difficulty is that I can see in the dynamic performance views that it is running, for instance using this query:
SELECT S.USERNAME,
s.sid,
s.osuser,
t.sql_id,
sql_text
FROM v$sqltext_with_newlines t,
V$SESSION s
WHERE t.address =s.sql_address
AND t.hash_value = s.sql_hash_value
AND s.status = 'ACTIVE'
AND s.username <> 'SYSTEM'
ORDER BY s.sid,
t.piece;
But that will return the entire script, not the statement it's currently at. Is there any way to figure this out?
Upvotes: 3
Views: 2047
Reputation: 9779
What @Kombajn zbożowy suggested is the best way to track plsql execution at runtime - if you prepared for that and set up the calls in your script.
If you got stuck with code that's not using dbms_application_info
:
v$session
has several helpful columns
v$session.sql_id
will give you the current running sql statement -
even when executed in a plsql block.
v$session.event
- gives you the wait event. i think that
dbms_lock
is considered idle (check for your self).
v$session.ROW_WAIT_OBJ#
is the object_id
(dba_objects.object_id
) of the current object in the wait event.
v$active_session_info
- snapshot of v$session
. you can trace back
the session since a given time and query the columns mentioned above.P.S one other thing, instead of looping every 60 seconds and check if the date has passed - isn't it simpler to calculate the number of seconds till the desired time and just wait ?
Upvotes: 1
Reputation: 10703
I'm not aware of any way to get currently executing line of a PL/SQL program.
But you can use dbms_application_info.set_module/set_action
before the sleep statement and it will be visible in v$session.module/action
columns.
SQL> select sys_context('USERENV', 'SID') from dual;
SYS_CONTEXT('USERENV','SID')
--------------------------------------------------------------------------------
273
SQL> exec dbms_application_info.set_module('My program', 'Waiting for the hell to freeze');
PL/SQL procedure successfully completed.
SQL> exec dbms_lock.sleep(60);
....
In another session:
SQL> select sid, module, action from v$session where sid = 273;
SID MODULE ACTION
---------- ---------------------- ----------------------------------
273 My program Waiting for the hell to freeze
Upvotes: 6