session 1: scott@prodselect * from dept1 where deptno=40 for update; session 2: scott@produpdate dept1 set deptno=41 where deptno=40; 这时候session 2就被卡住了 首先你要知道为啥会卡住 可以通过v$session event列查看一下等待事件 那么就需要si
session 1:
scott@prod>select * from dept1 where deptno=40 for update;
session 2:
scott@prod>update dept1 set deptno=41 where deptno=40;
这时候session 2就被卡住了
首先你要知道为啥会卡住
可以通过v$session event列查看一下等待事件 那么就需要sid,可是session 2卡住了啊,我没法直接在session 2中查sid 可以通过sql_id查出sid
sys@prod>select sql_id,sql_text from v$sql where sql_text like 'update dept1%'; sql_id sql_text ------------- -------------------------------------------------- 8xxzy0hngvv6m update dept1 set deptno=41 where deptno=40
有了sql_id好像不需要sid了啊…╮(╯▽╰)╭
sys@prod>select sid,event,p1,p2 from v$session where sql_id='8xxzy0hngvv6m'; sid event p1 p2 ---------- ---------------------------------------------------------------- ---------- ---------- 44 enq: tx - row lock contention 1415053318 196621
现在知道原因了,原来是在等待tx锁,看来有人没commit啊 那么我们现在就要查出是那个会话blocking了我们 我的笨方法: 在v$lock视图中有id1,id2这两列 对于tm锁来说,id1表示被锁定的对象的对象id,id2始终为0 对于tx锁里说,id1表示事物使用的回滚段编号以及在事物表中对应的记录编号,id2表示该记录编号被重用的次数(wrapp) 那么我们知道一个当执行dml操作时,会在表上加tm锁 查一下dept1表的object_id
sys@prod>select object_id from dba_objects where object_name ='dept1'; object_id ---------- 77723
查出sid
sys@prod>select sid from v$lock where id1= 77723 ; sid ---------- 44 46
sys@prod>select * from v$lock where sid in(44,46); addr kaddr sid ty id1 id2 lmode request ctime block ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 00000000844d1f10 00000000844d1f68 46 ae 100 0 4 0 2870 0 00000000844d21b0 00000000844d2208 44 ae 100 0 4 0 4472 0 00000000844d2d28 00000000844d2d80 44 tx 196621 1408 0 6 2833 0 00002b0b14d46228 00002b0b14d46288 44 tm 77723 0 3 0 2833 0 00002b0b14d46228 00002b0b14d46288 46 tm 77723 0 3 0 2867 0 00000000832749e8 0000000083274a60 46 tx 196621 1408 6 0 2841 1
真相大白了 44号会话(session 2)需要获取tx锁,在他的request列值为6 46号会话(session 1)持有了tx锁,在他的lmode列值为6 ,block列值为1表示它阻塞了别人获取lomde为6的锁 把session 46 kill了就好了,kill之前记得问一下客户
alter system kill session 'sid,serial#';
简单的方法: 得知等待事件是enq: tx – row lock contention,行锁,接下来就是要找到谁锁住了这个会话。在10gr2以后,只需要gv$session视图就可以迅速定位blocker,通过blocking_instance和blocking_session字段即可。
sys@prod>select sid,inst_id,blocking_instance,blocking_session from gv$session where sid=44; sid inst_id blocking_instance blocking_session ---------- ---------- ----------------- ---------------- 44 1 1 46
关于tx锁的id1和id2 对于tx锁里说,id1表示事物使用的回滚段编号以及在事物表中对应的记录编号,id2表示该记录编号被重用的次数(wrapp) 可以从v$lock_type得到解释
sql> select id1_tag,id2_tag from v$lock_type where type='tx'; id1_tag id2_tag --------------- ---------- usn