You are on page 1of 5

Locking issues in Oracle Database 10g

Many a times we face some issue, that a perticular sql query is holding a lock(s) on certain object. This will impact concurrency issue also for other DMLs. Some other user may complaint that he is using a DML query(Insert/delete/update) and qurey is taking lot of time. One of the reason for this might be that, the object which 2nd query wants to use is already locked by first query. In Oracle database 10g we can check the objects, which are locked by any other user. We have a table called V$LOCKED_OBJECTS, which lists all locks acquired by every transaction on the system. Example, lets say a user is holding lock on certain table by some DML query from long time. As a DBA you want to find out the session and kill the same so that other can use the resource. Following steps can be followed to get this info and remove the lock. SQL> select object_id, session_id, oracle_username, os_user_name, process from v$locked_object 2; OBJECT_ID SESSION_ID ORACLE_USERNAME OS_USER_NAME PROCESS - - 1991774 368 APPS plnops 26188 2019121 368 APPS plnops 26188 34376 507 APPS plnops 25922 Based on the above output you can check the object, which the user has locked. Example, if we take a object ID 1991774, then following query will give us the output as object_name. SQL> select object_name from dba_objects where object_id = 34403; OBJECT_NAME MSC_ST_DEMANDS Also from SESSION_ID value we can get the session details of the user. Lets check for SESSION_ID 368. Here the SESSION_ID column of V$LOCKED_OBJECT is same as SID column of V$SESSION. SQL> select SID, SERIAL#, sql_id from v$session where SID=368; SID SERIAL# SQL_ID - - 368 545 ag47457n3xck1

From the SQL_ID we can easily get the SQL query, the user is using as shown below. SQL> select sql_text from v$sql 2 where sql_id = ag47457n3xck1; SQL_TEXT insert into MSC_ST_DEMANDS ( INVENTORY_ITEM_ID, SOURCE_INVENTORY_ITEM_ID, ORGANIZATION_ID, WIP_ENTITY_ID, SOURCE_WIP_ENTITY_ID, ORDER_NUMBER, WIP_STATUS_CODE, WIP_SUPPLY_TYPE, OPERATION_SEQ_NUM, USING_REQUIREMENT _QUANTITY, QUANTITY_ISSUED, USING_ASSEMBLY_ITEM_ID, DEMAND_TYPE, PRO JECT_ID, TASK_ID, PLANNING_GROUP, END_ITEM_UNIT_NUMBER, DEMAND_CLASS , ORIGINATION_TYPE, USING_ASSEMBLY_DEMAND_DATE, MPS_DATE_REQUIRED, D ELETED_FLAG, QUANTITY_PER_ASSEMBLY, ASSET_ITEM_ID, ASSET_SERIAL_NUMBER, COMPONENT_SCALING_TYPE, COMPONENT_YIELD_FACTOR, REFRESH_ID, SR_INST ANCE_ID) select x.INVENTORY_ITEM_ID, x.INVENTORY_ITEM_ID, x.ORGANIZATI ON_ID, x.WIP_ENTITY_ID, x.WIP_ENTITY_ID, x.WIP_ENTITY_NAME, x.STATU S_CODE, x.WIP_SUPPLY_TYPE, x.COPY_OP_SEQ_NUM, x.NEW_REQUIRED_QUANTITY, SQL_TEXT x.QUANTITY_ISSUED, x.JOB_REFERENCE_ITEM_ID, x.DEMAND_TYPE, x.PROJECT_I D, x.TASK_ID, x.PLANNING_GROUP, The above query gives first 1000 characters of SQL query. To get the complete SQL you can check the column SQL_FULLTEXT in same table(V$SQL). Once you get the session information for SQL, you can kill the session using following commands. SQL> alter system kill session 368, 545; System altered.

Check performance after killing 1 session. Usually the performance improves and other users will appriciate you, as there query will run faster. (:-)). ====================================== SELECT vs.username, vs.osuser, vh.sid locking_sid, vs.status status, vs.module module, vs.program program_holding, jrh.job_name, vsw.username, vsw.osuser, vw.sid waiter_sid, vsw.program program_waiting, jrw.job_name, 'alter system kill session ' || ''''|| vh.sid || ',' || vs.serial# || ''';' "Kill_Command" FROM v$lock vh, v$lock vw, v$session vs, v$session vsw, dba_scheduler_running_jobs jrh, dba_scheduler_running_jobs jrw WHERE (vh.id1, vh.id2) IN (SELECT id1, id2 FROM v$lock WHERE request = 0 INTERSECT SELECT id1, id2 FROM v$lock WHERE lmode = 0) AND vh.id1 = vw.id1 AND vh.id2 = vw.id2 AND vh.request = 0 AND vw.lmode = 0 AND vh.sid = vs.sid AND vw.sid = vsw.sid AND vh.sid = jrh.session_id(+) AND vw.sid = jrw.session_id(+); =================================================== select c.owner, c.object_name, c.object_type, b.sid, b.serial#, b.status,

b.osuser, b.machine from v$locked_object a , v$session b, dba_objects c where b.sid = a.session_id and a.object_id = c.object_id / ============== select blocking_session, sid, serial#, wait_class, seconds_in_wait from v$session where blocking_session is not NULL order by blocking_session; ========================== Find Locks or Identifying sessions holding or acquiring the lock Finding Locked Objects : (Identifier for session holding or acquiring the lock) For more info regarding locks : search in google :v$lock. SQL> SELECT DECODE(request,0,'Holder: ','Waiter: ')||sid sess, id1, id2, lmode, request, type FROM V$LOCK WHERE (id1, id2, type) IN (SELECT id1, id2, type FROM V$LOCK WHERE request>0) ORDER BY id1, request; SESS ID1 ID2 ------------------------------------------------ ---------- ---------LMODE REQUEST TY ---------- ---------- -Holder: 336 1376264 27170 6 0 TX Waiter: 32 0 6 TX 1376264 27170

Find the serial number of sid from v$session; then kill the session and release the lock ? Select serial# from v$session where sid=336; O/p Serial# 121 Now Kill the session alter system kill session '336,121' immediate; Which Sid is blocking which Sid ? 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; SID 'ISBLOCKING SID ---------- ----------- ---------336 IS BLOCKING 32 Show sid blocking plus machine name also ? select s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ' ) is blocking ' || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status from v$lock l1, v$session s1, v$lock l2, v$session s2 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 ; BLOCKING_STATUS -------------------------------------------------------------------------------APPS@maxindia-9a85e7 ( SID=336 ) is blocking APPS@erpdev ( SID=32 )

You might also like