基本的にV$SESSIONをみればロックで待たされているセッションと、ロックしているセッションがわかります。BLOCKING_SESSION_STATUS=’VALID’の条件で、現在待たされているセッションを特定しす。
ロック対象セッションの特定SQL
select ws.SID -- 待たされているセッションID ,ws.SERIAL# ,ws.STATUS ,ws.LAST_CALL_ET -- 今の状態になってからの経過時間 ,ls.SID -- ロックしているセッションID ,ls.SERIAL# ,ls.STATUS ,ls.LAST_CALL_ET -- 今の状態になってからの経過時間 from v$session ws inner join v$session ls on ws.BLOCKING_SESSION = ls.SID and ws.BLOCKING_SESSION_STATUS='VALID' ;
ロック対象セッションの特定SQL(ロック対象テーブルも表示)
実際現場ではRAC環境である事や、その他の情報もあわせて見たいので、これにdba_objectsや、v$locked_objectを結合して表示させています。
select ----待たされている側のsession情報 ws.INST_ID ,ws.SID ,ws.SERIAL# ,ws.USERNAME ,ws.LOCKWAIT -- ロックのアドレス。ロックがない場合はNULL ,ws.STATUS ,ws.LAST_CALL_ET -- 今の状態になってからの経過時間 ,ws.SQL_ID -- 待たされているSQL ,ws.EVENT -- ロックが発生しているオブジェクト ,o.OBJECT_ID ,o.OWNER ,o.OBJECT_NAME ,ws.ROW_WAIT_BLOCK# -- ロック対象行の存在するブロック ,ws.row_wait_row# -- ロック対象オブジェクトの対象行 --- 待ちの原因となっているセッション ,ls.INST_ID ,ls.SID ,ls.SERIAL# ,ls.USERNAME ,ls.SQL_ID ,ls.BLOCKING_SESSION_STATUS -- 当セッションをブロックしているセッションの有無 ,ls.STATUS ,ls.LAST_CALL_ET -- 今の状態になってからの経過時間 ,decode(k.LOCKED_MODE ,0, 'ロック要求中' -- まだ取得できていない ,1, 'NULL' ,2, '行共有(SS)' -- 行共有ロック ,3, '行排他(SX)' -- 行排他表ロック ,4, '共有(S)' -- 共有表ロック ,5, '共有行排他(SRX)' -- 共有行排他表ロック ,6, '排他(X)' -- 排他表ロック ,'???' ) locked_mode_dec ,ls.PROGRAM ,ls.MACHINE ,ls.EVENT from gv$session ws --待たされているセッション inner join gv$session ls --ロックしているセッション(トランザクション発生中) on ws.BLOCKING_INSTANCE = ls.INST_ID and ws.BLOCKING_SESSION = ls.SID inner join gv$locked_object k on ls.SID = k.SESSION_ID left outer join dba_objects o on ws.ROW_WAIT_OBJ# = o.OBJECT_ID where ws.BLOCKING_SESSION_STATUS ='VALID' ;