col DML_BLOCKING format a45
col DML_In_Waiting format a45
set linesize 400
set pagesize 3000
-- LABEL: STATEMENT A
select distinct
a.sid as Waiting_SID
,d.sql_text as DML_In_Waiting
,o.Owner as Object_Owner
,o.Object_Name as Locked_Object
,a.Blocking_Session as Blocking_SID
,c.sql_text as DML_Blocking
from
v$session a
,v$active_session_history b
,v$sql c
,v$sql d
,all_objects o
where
a.event = 'enq: TX - row lock contention'
and a.sql_id = d.sql_id
and a.blocking_session = b.session_id
and c.sql_id = b.sql_id
and a.Row_Wait_Obj# = o.Object_ID
and b.Current_Obj# = a.Row_Wait_Obj#
and b.Current_File# = a.Row_Wait_File#
and b.Current_Block# = a.Row_Wait_Block#
-- LABEL: STATEMENT B
select distinct
a.sid as Waiting_SID
,a.event as Event
,c.sql_text as DML_Blocking
,b.sid as Blocking_SID
,b.event as Event
,b.sql_id as Blocking_SQL_ID
,b.prev_sql_id as Blocking_Prev_SQL_ID
,d.sql_text as DML_Blocking
from
v$session a
,v$session b
,v$sql c
,v$sql d
where
a.event = 'enq: TX - row lock contention'
and a.blocking_session = b.sid
and c.sql_id = a.sql_id
and d.sql_id = nvl(b.sql_id,b.prev_sql_id);
The first statement is generally more accurate than the second, since
the session holding the lock may have issued several DML
statements since issuing the lock, so the DML that is output
as holding the lock may not be related to the blocking DML.
Occasionally you may find that the SQL_ID for the
session holding the lock is NULL, reason being that since issuing the
lock some PL/SQL code may have executed or a COMMIT is being performed
or some other ongoing latch activity is busy, in which case there
is no SQL_ID to identify the session with.
In such cases, join to NVL(B.SQL_ID,B.PREV_SQL_ID).
Sample output after simulating a blocking and waiting session;
In session 1, issue a full table lock;
create table test_lock (a varchar2(2), bb varchar2(2));
insert into test_lock values ('i', '1');
insert into test_lock values ('ii','2');
commit;
select * from test_lock for update;
In session 2, issue an update on one of the rows in table TEST_LOCK
update test_lock set a='i' where bb='1';
The above UPDATE statement will simply hang. Do not issue a rollback
in session1.
In Session 1, run the first SQL statement, labelled as "STATEMENT A" above.
Sample output;
WAITING_SID DML_IN_WAITING OBJECT_OWNER LOCKED_OBJECT BLOCKING_SID DML_BLOCKING
----------- --------------------------------------- ------------ ------------------------------ ------------ ----------------------------------
2081 update test_lock set a='i' where bb='1' USER1 TEST_LOCK 382 select * from test_lock for update