Finding root blocker (enqueue)
Subject: Detecting Blocking Sessions in RAC and non-RAC (Enqueue Locks) Environments
Doc ID: Note:398519.1 Type: SCRIPT
Last Revision Date: 12-JAN-2007 Status: PUBLISHED
In this Document
Configuring the Script
Running the Script
Applies to: Oracle Server - Enterprise Edition - Version: 7.3.4 to 10.2
Information in this document applies to any platform.
PurposeScript and explanation for finding blocking and blocked sessions in both RAC (multi
instance) and non-RAC (single instance) environments.
Resources (rows, tables, control files ...) represented by enqueues (TX, TM, CF, ...) can be
locked in various modes (i.e. shared, exclusive, ...). Concurrent locking requests can conflict as
per compatibility rules. Resources (enqueues) are externalized via GV$RESOURCE and lock
requests via GV$LOCK views. Details can be found in
'Oracle® Database Concepts' -> chapter 'Data Concurrency and Consistency' (10.2. version)
Locking Conflict Types
1. Local locking conflict (block) - conflicting sessions are connected to the same instance (also
applies to one instance of RAC)
Drawback: V$LOCK column BLOCK contains value 1 for blocking lock (session)
2. Global locking conflict (block) - conflicting sessions are connected to different instances
(multi instance RAC only)
Drawback: V$LOCK column BLOCK contains value 2 to mark potential conflict (value is
always 2 in RAC environments unless there is local conflict)
@ as per Bug:3230663 in 10.2 we should be able to detect global conflict (but still reproducible
in 10.2.0.2 @ Linux x86 )
Display all sessions holding or requesting lock of resource some session is waiting for. Waiting
session has non-zero value of column GV$LOCK.REQUEST. Resource is identified by
(TYPE,ID1,ID2 columns of GV$LOCK view).
We cannot use GV$LOCK.BLOCK in RAC as it always contains value 2 ("potential locking
conflict") unless there is local conflict detected.
Finding root blocker
Run query provided in Script section and do one of the following.
(1) Find and kill root blockers
a) - Find oldest resource request - row with highest CTIME (this is row L1)
b) - Exists there another row with the same SID as L1? (this is row L2 if exists)
NOT - this is root blocker, kill it
YES - Find row with the same values of ID1,ID2 columns as in L2 where LOCK > 0 (this is row
- Repeat (b) with L3 (L3 becomes L1) until You find root blocker
(2) Or use simple rule (may not be best)
a) Kill oldest blocking session (highest CTIME)
b) Run script again and repeat (a) until blocking session exists
Detecting Object of Locking Conflict
Typically problematic conflicts happen with "DML Locks" (transaction - TX and table - TM
lock types) and sometimes it is important to find out subject of the conflict (i.e. fix application
design error to prevent issue).
Object name for TM lock can be easily identified as V$LOCK.ID1 is matching to
select OBJECT_ID, OWNER,OBJECT_NAME from dba_objects o, V$LOCK l
where l.SID=&sid and l.ID1=o.OBJECT_ID;
Contrary there is no easy way (select) to find out which row (TX) is the session waiting for i.e. to
match TX request to TM lock (table name). This is due to locking implementation - pointer in
database block points to assigned slot in undo segment (transaction id - XID). It is possible to
make a guess of table name (using similarity of CTIME column value). I.e. session is waiting for
TX lock for 100s and TM lock on table A has been placed 100s ago (this is just a guess as TM
lock could have been acquired for earlier update in the same transaction).
Note: For simplicity GV$LOCK is referred as view but actually this is synonym for view
GV_$LOCK (the same applies to V$LOCK).
Configuring the ScriptThere are no steps required.
Running the ScriptConnect as user able to select from GV$LOCK (typically user having DBA
sqlplus '/ as sysdba'
CautionThis script is provided for educational purposes only and not supported by Oracle
Support Services. It has been tested internally, however, and works as documented. We do not
guarantee that it will work for you, so be sure to test it in your environment before relying on it.
Proofread this script before using it! Due to the differences in the way text editors, e-mail
packages and operating systems handle text formatting (spaces, tabs and carriage returns), this
script may not be in an executable state when you first receive it. Check over the script to ensure
that errors of this type are corrected.
-- Author: firstname.lastname@example.org
prompt CTIME is in Seconds
set lines 120
col BLOCK for 9
col LMODE for 9
col INST_ID for 9
col REQUEST for 9
col SID for 999999
select INST_ID, SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME, BLOCK
from gv$lock where (ID1,ID2,TYPE) in
(select ID1,ID2,TYPE from gv$lock where request>0);
Script Output- example output showing two independent root conflicts
- there can be noted oldest conflict (sid 64 vs 38) is not the root as session 38 is blocked by
INST_ID SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- -------- ---------- --------- ------- ---------- ---------- ---------- ----------
2 212 TX 1114116 1399221 6 0 308 2
1 248 TX 1114116 1399221 0 6 304 0
4 67 TX 6225949 1244199 6 0 26 2
1 38 TX 6225949 1244199 0 6 23 0
2 64 TX 131103 2270514 0 6 117 0
1 38 TX 131103 2270514 6 0 171 2