oracle locks

To see which Oracle Sessions are Blocking

//example output//
[[image:example_blocked_oracle_session.JPG width=”1280″ height=”66″]]
script – [[file:blocking_locks.sql]]

select distinct
s1.username ||'@'|| s1.machine ||'(INST=' || s1.inst_id ||' SID_SERIAL#= '|| s1.sid ||'_'||s1.serial#||')' as Blocker
,s2.username||'@'||s2.machine||' (INST='||s1.inst_id||' SID_SERIAL# = '||s2.sid ||'_'||s2.serial#||' Event='|| s2.event ||')' AS Blockee
, s2.program ||'@'|| s1.machine as Program
,substr(ob.object_name,1,40) ||' SQL -> ' || s3.sql_text AS Blocked_OBJ_SQL, s4.sql_text AS Blocker_SQL
from gv$lock l1, gv$session s1, gv$lock l2
, gv$session s2, v$sql s3
, gv$active_session_history ash, v$sql s4, dba_objects ob, gv$locked_object lo
where s1.sid=l1.sid
and s2.sid=l2.sid
and l1.block=1
and l2.request >0
and l1.id1=l2.id1
and l2.id2=l2.id2
and s2.sql_id = s3.sql_id
and s1.prev_sql_id = s4.sql_id
and lo.object_id = ob.object_id
and lo.SESSION_ID = s2.sid
and s2.seconds_in_wait > 10;

Note
1. this is using global view of GV$SESSION_WAIT – and reports back on any session which has waited > 10 seconds. So if your case scenario is looking for sessions which are blocked for less period of time then change the final line in the above script as required.

and s2.seconds_in_wait > 10;

Be cautious when amending this time period, as some applications may have by design, plenty of transactions which do cause row lock transactions eg scheduling applications. Normally, the purpose of this script is to look for anomalies.

2. seconds_in_wait has been deprecated from oracle 11g+. Currently is still works in 11gR2. Future releases may not include this column
if this bothers you, then change script line :

and s2.seconds_in_wait > 10;

to read

and s2.WAIT_TIME_MICRO/1000000

* Click here for Further Reading on [[@http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/dynviews_3016.htm|gv_session_wait.]]

Test case

We can easily simulate a a blocking lock situation using a test table. We will open two sqlplus sessions to the database and then issue the following commands to demonstrate this

1. using sqlplus connect to the database, eg

C:sqlplus [username]/[password]@database_name
SQL*Plus: Release 11.2.0.1.0 Production on Wed Oct 5 13:33:26 2011
Copyright (c) 1982, 2010, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 – 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>

**Session A.**

here, we create a dummy table and insert some test data into it. Check the data via a select, and then lock all rows in the table :
# create table test(colA varchar2(1), colB varchar2(1));
# insert into test values (1,’a’);
# insert into test values (2,’b’);
# select * from test ;
# commit;
# select * from test for update;

SQL> create table test(colA varchar2(1), colB varchar2(1));
Table created.
SQL> insert into test values (1,'a');
1 row created.
SQL> insert into test values (1,'b');
1 row created.
SQL> select * from test ;
C C
- -
1 a
1 b
SQL> commit;
Commit complete.
sql> select * from test for update;

now we have locked all rows in the table.

so switching to another sqlplus session, using the same connection string as before
eg

C:sqlplus [username]/[password]@database_name
SQL>

lets first try and see if we can select any row data :

SQL> select * from test ;
C C
- -
1 a
1 b

good – expected behaviour as a row or table lock does not normally prevent us from seeing the before image. Now lets try updating a row :

SQL> update test set colA=’Z’ where colA=’1′;

now you should see the session hangs. And you can prove this from running the script as above giving us the example result of :
[[image:example_blocked_oracle_session.JPG width=”1280″ height=”66″]]

so back to **Session A** – lets close the lock

SQL> commit;
Commit complete
.

and then checking **session B**, you should see that the update has now completed :

SQL> update test set colA='Z' where colA='1';
1 row updated.

Leave a comment