初探oracle高级队列锁V$LOCK
来源:互联网 发布:马赛克复原软件 编辑:程序博客网 时间:2024/05/17 07:50
SQL> desc v$lock
Name Null? Type
----------------- -------- ------------
ADDR RAW(8) 锁在内存中的地址
KADDR RAW(8) 锁在内存中的地址
SID NUMBER 持有锁的会话
TYPE VARCHAR2(2) 锁的类型:如TM,TX
ID1 NUMBER 锁的标识符1(不同类型的锁,ID1和ID2的含义也不相同)
ID2 NUMBER 锁的标识符2
LMODE NUMBER 会话持有锁的级别
REQUEST NUMBER 请求持有锁的级别
CTIME NUMBER 请求锁的时间,单位秒
BLOCK NUMBER 是否堵塞了其它会话。0或1,0表示没有阻塞
Session 1
sqlplus / as sysdba
startup
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
SQL> select * from v$lock;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- -
00000000BED5BA20 00000000BED5BA78 2 XR 4 0 1 0 52
00000000BED5BB00 00000000BED5BB58 2 RD 1 0 1 0 52
00000000BED5BBE0 00000000BED5BC38 2 CF 0 0 2 0 52
00000000BED5BE80 00000000BED5BED8 2 RS 25 1 2 0 48
00000000BED5CC98 00000000BED5CCF0 43 KD 0 0 6 0 47
00000000BED5C660 00000000BED5C6B8 43 KT 12876 0 4 0 47
00000000BED5D0F8 00000000BED5D150 44 TS 3 1 3 0 47
00000000BED5D730 00000000BED5D788 45 AE 100 0 4 0 47
00000000BED5D650 00000000BED5D6A8 45 TO 79833 1 3 0 47
00000000BED5C4A0 00000000BED5C4F8 129 AE 100 0 4 0 47
00000000BED5C740 00000000BED5C798 170 MR 7 0 4 0 48
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- -
00000000BED5C838 00000000BED5C890 170 MR 8 0 4 0 48
00000000BED5BDA0 00000000BED5BDF8 170 MR 9 0 4 0 48
00000000BED5CD78 00000000BED5CDD0 170 MR 10 0 4 0 48
00000000BED5D018 00000000BED5D070 170 MR 11 0 4 0 48
00000000BED5C120 00000000BED5C178 170 MR 1 0 4 0 48
00000000BED5C200 00000000BED5C258 170 MR 2 0 4 0 48
00000000BED5C918 00000000BED5C970 170 PW 1 0 3 0 46
00000000BED5CBB8 00000000BED5CC10 170 MR 4 0 4 0 48
00000000BED5C580 00000000BED5C5D8 170 MR 5 0 4 0 48
00000000BED5C9F8 00000000BED5CA50 170 MR 3 0 4 0 48
00000000BED5CAD8 00000000BED5CB30 170 MR 6 0 4 0 48
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- -
00000000BED5C2E0 00000000BED5C338 170 MR 201 0 4 0 48
00000000BED5BCC0 00000000BED5BD18 213 RT 1 0 6 0 48
24 rows selected.
查看当前数据库所有持有的锁
Session 2
SQL> select sid from v$mystat where rownum=1;
SID
----------
90
Session 1
SQL> select * from v$lock where sid=90;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BED5DFF0 00000000BED5E048 90 AE 100 0 4 0 400
在开启90号会话的同时,Oracle自动加了AE锁来保护会话。
Session 2
SQL> update cheng_t1 set name='BBBBBB' where id=1;
1 row updated.
Session 1
SQL> select * from v$lock where sid=90;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BED5DFF0 00000000BED5E048 90 AE 100 0 4 0 1100
00007F87C64CA7A8 00007F87C64CA808 90 TM 88681 0 3 0 200
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 200
90号会话增加持有了TM和TX锁
上面提到,不同类型的锁,ID1和ID2的含义也不相同,下面测试下TM锁的ID1含义;
SQL> select object_id,object_name from dba_objects where object_id=88681;
OBJECT_ID OBJECT_NAME
---------- --------------------------------------------------------------------------------------------------------------------------------
88681 CHENG_T1
可知TM锁ID1的意义为object_name,也就是表名;
TX锁的ID1和ID2含义:
SQL> select * from v$lock where sid=90 and type='TX';
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 730
SQL> select ADDR,XIDUSN,XIDSLOT,XIDSQN from v$transaction;
ADDR XIDUSN XIDSLOT XIDSQN---------------- ---------- --------- ----------
00000000BBF13A68 6 9 1691
v$transaction显示事务的唯一标识符;
可知:
ADDR地址相同,ID1=655369(十进制)=60009(十六进制),6和9,分别对应XIDUSN,XIDSLOT;ID2对应XIDSQN;
再开个会话模拟堵塞
Session 3
sqlplus cheng/oracle
SQL> select sid from v$mystat where rownum=1;
SID
----------
88
SQL> update cheng_t1 set name='BBBBBB' where id=1;
产生堵塞
Session 1
SQL> select * from v$lock where sid in(90,88) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F87C64D08F8 00007F87C64D0958 88 TM 88681 0 3 0 320
00000000BED5D9D0 00000000BED5DA28 88 AE 100 0 4 0 890
00000000BED5C040 00000000BED5C098 88 TX 3932251691 0 6 320
00007F87C64D08F8 00007F87C64D0958 90 TM 88681 0 3 0 2920
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 2921
00000000BED5DFF0 00000000BED5E048 90 AE 100 0 4 0 3820
可知:
1、90号会话TX锁BLOCK字段显示为1,堵塞了其它会话(即4号会话);
2、88号会话TX锁REQUEST显示为6,说明正在请求6号TX锁;
场景1:找出被堵塞的会话ID
SQL> select * from v$lock where sid=90;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BED5DFF0 00000000BED5E048 90 AE 100 0 4 0 7000
00007F87C642C638 00007F87C642C698 90 TM 88681 0 3 0 6100
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 6101
SQL> select * from v$lock where id1=393225 and id2=1691;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BED5C040 00000000BED5C098 88 TX 3932251691 0 6 4030
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 6631
可知被堵塞(或者是请求锁)的会话ID为88。
说明:通常情况下,TX锁的持有锁会话和请求锁会话的ID1和ID2数值是相同的。
场景2:定位行锁竞争数据块及信息
SQL> select sid,event,p1,p2,p3 from v$session where wait_class<>'Idle';
---------- ---------------------------------------------------------------- ---------- ---------- ----------
45 SQL*Net message to client 1650815232 1 0
88 enq: TX - row lock contention 1415053318 3932251691
SQL> select sid,event,p1,p2,p3,ROW_WAIT_OBJ#,ROW_WAIT_FILE#,ROW_WAIT_BLOCK#,ROW_WAIT_ROW# from v$session where wait_class<>'Idle';
SID EVENT P1 P2 P3 ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#
---------- ---------------------------------------------------------------- ---------- ---------- ---------- ------------- -------------- --------------- -------------
45 SQL*Net message to client 1650815232 1 0 5431 75736 0
88 enq: TX - row lock contention 1415053318 3932251691 886814 527 0
查看会话当前的等待事件
字段意义:
EVENT:会话等待的资源或事件
P1 P2 P3:附加参数
ROW_WAIT_OBJ#:指定行的表的对象ID — 即对象号,也是表名
ROW_WAIT_FILE# 指定行的数据文件标示符 — 即数据文件编号
ROW_WAIT_BLOCK#:指定行的块标识符 — 即块号
ROW_WAIT_ROW#:行号
说明:TX - row lock contention的意义为行锁竞争,是队列锁的等待事件。
SQL> select object_id,data_object_id from dba_objects where object_name='CHENG_T1';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
88681 88681
object_id指对象的数据字典号。数据库里对象的唯一,每一个对象都会被分配一个唯一的object_id作为区别的标志;
DATA_OBJECT_ID指包含对象的segment的字典对象编号。当Segment发生变动,这个数值也会改变。
这两个值都存放在Oracle数据字典里。一开始是相同的,当Segment发生了变动(如move表,或truncate表),DATA_OBJECT_ID就会改变(数字就会大一个)。
找到Rowid
SQL> select DBMS_ROWID.ROWID_CREATE(1,88681,4,527,0) from dual;
DBMS_ROWID.ROWID_C
------------------
AAAVppAAEAAAAIPAAA
DBMS_ROWID包允许我们使用PL/SQL程序或SQL语句创建rowids和获取rowid的信息。例如可以通过其找到数据对象编号,数据文件编号,包含数据行的数据块编号及数据块中的数据行。
具体用法查看10g官方文档 BOOK — PL/ — PL/SQL Packages and Types Reference — DBMS_ROWID
SQL> select * from cheng.cheng_t1 where rowid='AAAVppAAEAAAAIPAAA';
ID NAME
---------- ------------------------------
1 FFFFFF
通过Rowid查到堵塞88号会话的数据行
SQL> select sql_text,event from v$session a,v$sql b where a.sql_id=b.sql_id and sid=88;SQL_TEXT EVENT
--------------------------------------------------------- -------------------------------------------
update cheng_t1 set name='BBBBBB' where id=1 enq: TX - row lock contention
堵塞88号会话的sql语句
也可以dump出4号数据文件527号块获取更多信息
SQL> alter system dump datafile 4 block 527;
场景3:查看锁的会话信息:
SQL> select * from v$lock where sid in(90,88) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F87C642DA20 00007F87C642DA80 88 TM 88681 0 3 0 50510
00000000BED5D9D0 00000000BED5DA28 88 AE 100 0 4 0 51080
00000000BED5C040 00000000BED5C098 88 TX 3932251691 0 6 50510
00007F87C642DA20 00007F87C642DA80 90 TM 88681 0 3 0 53110
00000000BBF13A68 00000000BBF13AE0 90 TX 3932251691 6 0 53111
00000000BED5DFF0 00000000BED5E048 90 AE 100 0 4 0 54010
SQL> select sid,LOCKWAIT,status from v$session where sid in(90,88);
SID LOCKWAIT STATUS
---------- ---------------- --------
88 00000000BED5C098 ACTIVE
90 INACTIVE
这里指会话88请求持有一块锁,希望从内存分到地址,表现为LOCKWAIT(锁等待),内存地址即00000000BED5C098 ,与v$LOCK中88号会话TX锁的KADDR地址相对应;
STATUS状态:ACTIVE表示会话正在被堵塞或sql语句未执行结束;INACTIVE表示sql语句已执行完成,但不一定有commit;
详细会话信息
SQL> select SID,PADDR,PROGRAM,PROCESS,USERNAME,COMMAND,SQL_ID from v$session where sid in(90,88);
SID PADDR PROGRAM PROCESS USERNAMECOMMAND SQL_ID---------- ---------------- ------------------------------------------------ ------------------------ ------------------------------ ---------- -------------
88 00000000BE52B9A0 sqlplus@localhost.localdomain (TNS V1-V3) 3901 CHENG 6 b9qz0gya6zu4f
90 00000000BE531DF0 sqlplus@localhost.localdomain (TNS V1-V3) 3702 CHENG 0
SQL> select sql_text from v$sql where sql_id='b9qz0gya6zu4f';
SQL_TEXT----------------------------------------------------------------------------------------------------------------------------------------------------------------
update cheng_t1 set name='BBBBBB' where id=1
根据SQL_ID找到引起堵塞的SQL语句
杀掉会话
SQL> select sid,SERIAL# from v$session where sid in(90,88);
SID SERIAL#---------- ----------
88 45
90 13
注意:
中止会话,通常有两种方法
本地:事务提交commit,事务回退rollback
远程:alter system kill session‘SID,SERIAL#’; 或者操作系统层kill-9 XXXX
System altered.
SQL> select * from v$lock where sid in(90,88) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000BED5D9D0 00000000BED5DA28 88 AE 100 0 4 0 61280
00000000BBF14478 00000000BBF144F0 88 TX 2621611093 6 0 630
00007F87C64AF310 00007F87C64AF370 88 TM 88681 0 3 0 60710
90号会话锁已被释放;88号会话成功持有了TX6号锁。SQL> select sid,LOCKWAIT,status from v$session where sid in(90,88);
SID LOCKWAIT STATUS
---------- ---------------- --------
88 INACTIVE
90 KILLED
88号会话STATUS显示INACTIVE,SQL语句执行完成;LOCKWAIT为空,已没有锁等待。
Session 2
SQL> select sid from v$mystat where rownum=1;
select sid from v$mystat where rownum=1
*
ERROR at line 1:
ORA-00028: your session has been killed
Session 3
SQL> update cheng_t1 set name='BBBBBB' where id=1;
1 row updated.
SQL> commit;
Commit complete.死锁的实验
Session 1不变,重新开启两会话
Session 2SQL> select sid from v$mystat where rownum=1;
SID
----------
175
SQL> update cheng_t1 set name='AAAAAA' where id=1;
1 row updated.
Session 3
SQL> select sid from v$mystat where rownum=1;
SID
----------
217
SQL> update cheng_t1 set name='bbbbbb' where id=2;
1 row updated.
Session 1
SQL> select * from v$lock where sid in (175,217) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F87C642DA20 00007F87C642DA80 175 TM 88681 0 3 0 660
00000000BBF530E8 00000000BBF53160 175 TX 5243161106 6 0 660
00000000BED5D8F0 00000000BED5D948 175 AE 100 0 4 0 830
00000000BBF53AF8 00000000BBF53B70 217 TX 3932321691 6 0 530
00007F87C642DA20 00007F87C642DA80 217 TM 88681 0 3 0 530
00000000BED5C660 00000000BED5C6B8 217 AE 100 0 4 0 630
此时两会话各持有TM、TX锁,并互相不堵塞
Session 2
SQL> update cheng_t1 set name='bbbbbb' where id=2;
会话175被堵塞
Session 1
SQL> select * from v$lock where sid in (175,217) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F87C64AF310 00007F87C64AF370 175 TM 88681 0 3 0 1240
00000000BBF530E8 00000000BBF53160 175 TX 5243161106 6 0 1240
00000000BED5D8F0 00000000BED5D948 175 AE 100 0 4 0 1410
00000000BED5D398 00000000BED5D3F0 175 TX 3932321691 0 6 270
00007F87C64AF310 00007F87C64AF370 217 TM 88681 0 3 0 1110
00000000BBF53AF8 00000000BBF53B70 217 TX 3932321691 6 0 1111
00000000BED5C660 00000000BED5C6B8 217 AE 100 0 4 0 1210
175号会话REQUEST=6,正在申请持有6号TX锁;217号会话TX锁BLOCK=1,说明堵塞了216号会话;
Session 3
SQL> update cheng_t1 set name='AAAAAA' where id=1;
会话217被堵塞(构成和会话175相互堵塞条件)
Session 2
SQL> update cheng_t1 set name='bbbbbb' where id=2;
update cheng_t1 set name='bbbbbb' where id=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
175号会话报出ORA-00060错误,自动删除死锁deadlockSession 1
SQL> select * from v$lock where sid in (175,217) order by sid;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F87C64AF310 00007F87C64AF370 175 TM 88681 0 3 0 2860
00000000BBF530E8 00000000BBF53160 175 TX 5243161106 6 0 2861
00000000BED5D8F0 00000000BED5D948 175 AE 100 0 4 0 3030
00000000BBF53AF8 00000000BBF53B70 217 TX 3932321691 6 0 2730
00007F87C64AF310 00007F87C64AF370 217 TM 88681 0 3 0 2730
00000000BED5CF38 00000000BED5CF90 217 TX 5243161106 0 6 860
00000000BED5C660 00000000BED5C6B8 217 AE 100 0 4 0 2830
175号会话TX锁BLOCK=1,堵塞了217号会话;217号会话TX锁REQUEST=6,在申请持有6号TX锁;
Linux窗口
看看死锁的相关日志
[oracle@localhost ~]$ oerr ora 00060
00060, 00000, "deadlock detected while waiting for resource"
// *Cause: Transactions deadlocked one another while waiting for resources.
// *Action: Look at the trace file to see the transactions and resources
// involved. Retry if necessary.
[oracle@localhost ~]$ cd $ORACLE_BASE
[oracle@localhost app]$ tail -f diag/rdbms/orcl/orcl/trace/alert_orcl.log
Tue Jun 06 23:01:06 2017
ORA-00060: Deadlock detected. More info in file /oracle/app/diag/rdbms/orcl/orcl/trace/orcl_ora_6747.trc.
Oracle在死锁发生后生成一份日志,有时Oracle接着会自动启动Smon进程
[oracle@localhost app]$ more /oracle/app/diag/rdbms/orcl/orcl/trace/orcl_ora_6747.trc
......
*** 2017-06-06 23:01:06.270
DEADLOCK DETECTED ( ORA-00060 )
[Transaction Deadlock]
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-0008001c-00000452 22 175 X 23 217 X
TX-00060010-0000069b 23 217 X 22 175 X
session 175: DID 0001-0016-00000164 session 217: DID 0001-0017-000000B1
session 217: DID 0001-0017-000000B1 session 175: DID 0001-0016-00000164
Rows waited on:
Session 175: obj - rowid = 00015A69 - AAAVppAAEAAAAIPAAB
(dictionary objn - 88681, file - 4, block - 527, slot - 1)
Session 217: obj - rowid = 00015A69 - AAAVppAAEAAAAIPAAA
(dictionary objn - 88681, file - 4, block - 527, slot - 0)
----- Information for the OTHER waiting sessions -----
Session 217:
sid: 217 ser: 37 audsid: 280258 user: 90/CHENG
flags: (0x45) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
flags2: (0x40009) -/-/INC
pid: 23 O/S info: user: oracle, term: UNKNOWN, ospid: 6749
image: oracle@localhost.localdomain (TNS V1-V3)
client details:
O/S info: user: oracle, term: pts/1, ospid: 6748
machine: localhost.localdomain program: sqlplus@localhost.localdomain (TNS V1-V3)
application name: SQL*Plus, hash value=3669949024
current SQL:
update cheng_t1 set name='AAAAAA' where id=1
----- End of information for the OTHER waiting sessions -----
Information for THIS session:
----- Current SQL Statement for this session (sql_id=9rzgvs6xydnpk) -----
update cheng_t1 set name='bbbbbb' where id=2
===================================================
......
日志中包含产生死锁的会话信息,用户信息及产生死锁的语句等信息,帮助找到产生死锁原因。
- 初探oracle高级队列锁V$LOCK
- oracle--v$lock 字段详解
- ORACLE关于锁和V$LOCK的分析
- ORACLE关于锁和V$LOCK的分析
- oracle 关于锁和v$lock的分析
- oracle--v$lock type字段详解
- Oracle 动态性能视图之V$LOCK
- Oracle AQ高级队列
- Oracle高级队列介绍
- oracle 高级队列技术
- 你有多了解Oracle Enqueue lock队列锁机制?
- v$lock!
- V$LOCK
- Oracle 队列锁类型 Oracle Enqueue Lock Type Reference including 11g new locks
- UNIX环境高级编程——system V消息队列
- Oracle Lock 锁
- v$lock 和v$locked_object
- v$lock 和v$locked_object
- 在Docker中搭建Oracle数据库,并使用PL/SQL Developer链接
- 那些善良的人,一定要看。或许可以帮助你幸免于难
- Python 2.7.x 和 Python 3.x 的主要区别
- TP5自动验证机制
- [USACO08JAN]电话线Telephone Lines 洛谷P1948
- 初探oracle高级队列锁V$LOCK
- Spring Data Redis(sdr)-----序列化
- KLEE error reports
- ECharts 去掉地图(map)的指示图(visualMap)
- 深入理解JAVA集合系列二:ConcurrentHashMap源码解读
- solr历史版本
- 面试题3:数组中重复的数字
- 一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。找出这两个数字
- HDU-1233-还是畅通工程(最小生成树kruscal)