Wednesday, 22 December 2010

how to work with locks in oracle ???

Understanding and Troubleshooting Locks in Oracle


What’s Causing My Session to Hang?


When an application slows down or users face unresponsive transactions, a common culprit is blocking caused by session locks. Pinpointing not only the session responsible for the block but also the specific object or row involved can save time and frustration. Let’s walk through how to create, identify, and investigate such scenarios.



---


Simulating a Blocking Lock


To explore lock behavior, start by creating a test case with two database sessions.


In Session 1:


CREATE TABLE tstlock (foo VARCHAR2(1), bar VARCHAR2(1));

INSERT INTO tstlock VALUES (1, 'a');

INSERT INTO tstlock VALUES (2, 'b');

COMMIT;


Now lock the entire table:


SELECT * FROM tstlock FOR UPDATE;


In Session 2, attempt a conflicting update:


UPDATE tstlock SET bar = 'a' WHERE bar = 'a';


This command will hang, waiting for the lock held by Session 1 to be released.



---


Identifying the Blocking Session


Oracle’s DBA_BLOCKERS view shows the sessions causing blocks, but a more detailed and faster method is through the V$LOCK view:


SELECT * FROM v$lock;


Look at the BLOCK column: a value of 1 indicates a session that is blocking others. To determine which session is blocked by which, compare the ID1 and ID2 values for matches, and use this query:


SELECT l1.sid || ' IS BLOCKING ' || l2.sid

FROM v$lock l1, v$lock l2

WHERE l1.block = 1 AND l2.request > 0

AND l1.id1 = l2.id1 AND l1.id2 = l2.id2;


For more readability:


SELECT s1.username || '@' || s1.machine || ' (SID=' || s1.sid || ') is blocking ' ||

       s2.username || '@' || s2.machine || ' (SID=' || s2.sid || ')' AS blocking_info

FROM v$lock l1

JOIN v$session s1 ON l1.sid = s1.sid

JOIN v$lock l2 ON l1.id1 = l2.id1 AND l1.id2 = l2.id2

JOIN v$session s2 ON l2.sid = s2.sid

WHERE l1.block = 1 AND l2.request > 0;



---


Lock Types and the Meaning of ID1/ID2


Understanding the TYPE, ID1, and ID2 columns in V$LOCK helps decode lock behavior:


TX: Row-level transaction lock (common in DML).


TM: DML operation on an object (e.g., a table).


UL: User-defined lock via DBMS_LOCK.



For TX locks, ID1 and ID2 identify rollback and transaction entries. For TM locks, ID1 maps to the object being modified.



---


Lock Modes: LMODE and REQUEST


Oracle lock modes range from 0 (no lock) to 6 (exclusive lock). If a session holds an exclusive TX lock (LMODE=6) and another session wants it, the second session will show REQUEST=6 and LMODE=0.


You might also see TX-4 locks when sessions wait for ITL (Interested Transaction List) entries. This usually indicates a need to increase INITRANS on the affected table.



---


Determining the Locked Object


To find the exact object being locked:


SELECT object_name FROM dba_objects WHERE object_id = <ID1 value>;


This reveals the table or object name associated with the TM lock.



---


Finding the Locked Row


To go deeper and find the specific row that a session is waiting for:


SELECT row_wait_obj#, row_wait_file#, row_wait_block#, row_wait_row#

FROM v$session

WHERE sid = <blocked session SID>;


Combine this with DBMS_ROWID.ROWID_CREATE to reconstruct the actual rowid:


SELECT do.object_name,

       dbms_rowid.rowid_create(1, s.row_wait_obj#, s.row_wait_file#, s.row_wait_block#, s.row_wait_row#) AS row_id

FROM v$session s

JOIN dba_objects do ON s.row_wait_obj# = do.object_id

WHERE s.sid = <blocked session SID>;


You can then query the row directly:


SELECT * FROM tstlock WHERE rowid = '<generated ROWID>';



---


Final Thoughts


This walkthrough demonstrates how to detect blocking locks in Oracle and investigate down to the exact row causing the issue. By combining views like V$LOCK, V$SESSION, and DBA_OBJECTS, you gain powerful tools to resolve and understand locking problems efficiently.