独立思考锁表了咋整
程序员文章站
2022-04-25 17:42:24
...
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
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 00002B0B【本文来自鸿网互联 (http://www.68idc.cn)】14D46288 46 TM 77723 0 3 0 2867 0
00000000832749E8 0000000083274A60 46 TX 196621 1408 6 0 2841 1
sys@PROD>SELECT XIDUSN,XIDSLOT,XIDSQN FROM v$transaction WHERE addr='00000000832749E8';
XIDUSN XIDSLOT XIDSQN
---------- ---------- ----------
3 13 1408
XIDSQN和ID2很容易对上了
ID1 和 XIDUSN、XIDSLOT怎么对呢
将196621转换成16进制是0X3000D
然后分高位和低位分别再转换为10进制,高位的16进制3就是十进制的3,也就是XIDUSN=3,而低位的16进制0D转换为10进制是13,也就是XIDSLOT=13。