TX锁最常见的有以下4种情况:

由于行被活动事务锁住导致的等待。

由于唯一约束或主键约束导致的等待。

由于数据块ITL槽不足导致的等待。

由于行包含在同一个位图索引片段中导致的等待。

在LDY用户下创建一张表,插入几条数据:

CREATE TABLE tx_eg (id number,name varchar2(10),sex varchar2(10)) INITRANS 1 MAXTRANS 1;

INSERT into tx_eg VALUES (1,'liaowh','MALE');

INSERT into tx_eg VALUES (2,'liaody','MALE');

INSERT into tx_eg VALUES (3,'wanghh','MALE');

INSERT into tx_eg VALUES (4,'zhangxx','FEMALE');

INSERT into tx_eg VALUES (5,'linjx','MALE');

COMMIT;

1.由于行被活动事务锁住导致的等待:

两个session同时update同一条记录。

Ses#1:  update tx_eg set name='yangkq' where id=5;

Ses#2: update tx_eg set name='yangkq' where id=5;

DBA用户查看:

select SID,TYPE,ID1,ID2,LMODE,REQUEST from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

144 TX     327692       8218          0          6

146 TX     327692       8218          6          0

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: 146        327692       8218          6          0 TX

Waiter: 144        327692       8218          0          6 TX

可以看出SID 144等待SID 146。SID 146持有1个排他锁(LMODE=6),而SID 144同样请求以排他形式获得该锁(REQUEST=6)。

由enqueue的概念可知,通过TYPE-ID1-ID2标识一个锁,所以这两个锁是同一个锁。

可以通过查询V$SESSION视图,找出具体对象的具体行。

通过以下四个字段:

ROW_WAIT_OBJ#                                      NUMBER

ROW_WAIT_FILE#                                     NUMBER

ROW_WAIT_BLOCK#                                    NUMBER

ROW_WAIT_ROW#                                      NUMBER

DBA用户查看:

select ROW_WAIT_OBJ#,

ROW_WAIT_FILE#,

ROW_WAIT_BLOCK#,

ROW_WAIT_ROW#

from v$session

where sid=144;

ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#

------------- -------------- --------------- -------------

54398             14          102391             4

SID 144等待的对象号是54398,所在文件是FILE 14,等待的行所在的块号是102391,行号是4。

通过对象号,或是文件号+块号,都可以查找到该对象:

select owner,object_name,object_type from dba_objects where object_id=54398;

OWNER      OBJECT_NAME          OBJECT_TYPE

---------- -------------------- --------------------

LDY        TX_EG                TABLE

select segment_name, segment_type, owner

from dba_extents

where file_id = 14

and 102391 between block_id

and block_id + blocks -1;

SEGMENT_NAME     SEGMENT_TYPE       OWNER

---------------- ------------------ ----------

TX_EG            TABLE              LDY

而ROW_WAIT_ROW#表示ROWID中的row number,可以通过dbms_rowid.rowid_row_number(rowid)获得该行的row number。

可以查找到具体行的内容:

select * from ldy.tx_eg where DBMS_ROWID.ROWID_ROW_NUMBER(ROWID)=4;

ID NAME       SEX

---------- ---------- ----------

5 linjx      MALE

这时session2由于等待而被挂起,需要等待session commit、rollback或转变问为一个in-doubt状态,才能继续。

2.由于唯一约束或主键约束导致的等待:

如果一张表存在主键约束,唯一性约束或唯一索引,该列就会因为唯一索引的约束强制该列的唯一性。如果两个session需要插入同一个键值,那么第二个session将会等待或收到ORA-0001错误。

为tx_eg表增加一个主键约束:

alter table tx_eg add constraint tx_eg_pk primary key(id);

两个session同时insert具有相同ID的记录。

Ses#1:  insert into tx_eg values (10,'Xiongwh','MALE');

Ses#2: insert into tx_eg values (10,'Zengx',null);

DBA用户查看:

select SID,TYPE,ID1,ID2,LMODE,REQUEST from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

144 TX     393258       7967          0          4

144 TX      65576       6264          6          0

146 TX     393258       7967          6          0

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: 146       393258       7967          6          0 TX

Waiter: 144       393258       7967          0          4 TX

可以看出SID 144等待SID 146。SID 146持有1个排他锁(LMODE=6),而SID 144请求以共享模式获得该锁(REQUEST=4)。

除此之外,SID 144自身还持有1个排他锁(LMODE=6)。

这时session2由于等待而被挂起,需要等待session commit、rollback或转变问为一个in-doubt状态,才能继续。

如果session1 commit,session2 则收到一个错误:ORA-00001: 违反唯一约束条件 (LDY.TX_EG_PK)。

如果session1 rollback,session2则可以顺利insert。

如果insert不同的ID记录或没有唯一性约束,则只有有2个TX排他锁,不存在阻塞。

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

144 TX     458752       6034          6          0

146 TX     589845       7585          6          0

3.由于数据块ITL槽不足导致的等待:

Oracle在每个数据块的顶部区域中的'interested transaction list'(ITL)保存被事务锁定的行。一个对象中的任何一个块的ITL槽的数量由参数INITRANS和参数MAXTRANS约束。INITRANS表示数据块在被创建时初始化的ITL数量。MAXTRANS表示ITL可以达到的最大数目。

MAXTRANS设置了在某一时间内,在数据块可以并发的事务数的上限。

INITRANS指定了数据块最小并发。

CREATE TABLE MT (id number(10),name varchar2(20)) INITRANS 1 MAXTRANS 1;

insert into MT values (1,'First');

insert into MT values (2,'Second');

insert into MT values (3,'Third');

SQL> select owner, INI_TRANS,max_TRANS from dba_tables where table_name='MT';

OWNER            INI_TRANS  MAX_TRANS

--------------- ---------- ----------

SCOTT                    1          1

Ses#1: update MT set name='Big' where ID=1;

Ses#2: update MT set name='Small' where ID=2;

Ses#3: update MT set name='Middle' where ID=3;

DBA用户查看:

select SID,TYPE,ID1,ID2,LMODE,REQUEST from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

9 TX     327716        328          6          0

13 TX     393243        331          6          0

14 TX     327716        328          0          4

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: 9                 327716        328          6          0 TX

Waiter: 14                327716        328          0          4 TX

从dump文件上看,尽管设置了MAXTRANS为1,但是每个数据块都至少有2个ITL事务槽,所以需要有3个session时,第3个session会被hang住。

下面是dump的部分截取,可以看到2个事务槽都满了。

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0004.002.0000012b  0x00800437.0052.57  ----    1  fsc 0x0001.00000000

0x02   0x0001.029.000000bc  0x00800180.0036.01  ----    1  fsc 0x0002.00000000

从Oracle 9.2开始,可以通过v$segment_statistics视图检查ITL等待。

查询语句如下:

set line 999

col OWNER for a20

col OBJECT_NAME for a30

col STATISTIC_NAME for a10

SELECT t.OWNER, t.OBJECT_NAME, t.OBJECT_TYPE, t.STATISTIC_NAME, t.VALUE

FROM v$segment_statistics t

WHERE t.STATISTIC_NAME = 'ITL waits'

AND t.VALUE > 0

ORDER BY VALUE DESC;

如有发现,可以适量增大INITTRANS和MAXTRANS。

关于ITL等待,需要之前的session1或session2处于决断状态(commit/rollback)之后才会统计ITL等待。

OWNER        OBJECT_NAME       OBJECT_TYPE        STATISTIC_     VALUE

------------ ----------------- ------------------ ---------- ---------

SCOTT        MT                TABLE              ITL waits          1

从10g开始表的MAXTRANS参数不能再设置,自动设置为255。从而不会导致ITL槽不足的而hang住的情况发生,但仍会等待分配ITL。

4.由于行包含在同一个位图索引片段中导致的等待:位图索引的索引键值包含一个范围的ROWID,所以位图索引中的每个条目(entry)可能包含实际表中的许多行。如果两个session想要更新的行包含在同一个位图索引片段中,那么第二个session需要等待第一个session COMMIT或ROLLBACK,在此期间等待获得mode 4的TX锁。

在tx_eg表的sex字段上建立一个位图索引:

CREATE Bitmap Index tx_eg_bitmap on tx_eg ( sex );

2个session分别update 2条不同的记录,但是这2条记录的sex字段的内容都是MALE。

Ses#1:  MALE->FEMALE

Ses#2:  MALE->FEMALE

Ses#1:  update tx_eg set sex='FEMALE' where id=2;

Ses#2:  update tx_eg set sex='FEMALE' where id=3;

DBA用户查看:

select SID,TYPE,ID1,ID2,LMODE,REQUEST from v$lock where type='TX';

SID TY        ID1        ID2      LMODE    REQUEST

---------- -- ---------- ---------- ---------- ----------

144 TX     327719       8220          0          4

144 TX     589864       7586          6          0

146 TX     327719       8220          6          0

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: 146       327719       8220          6          0 TX

Waiter: 144       327719       8220          0          4 TX

可以看出SID 144等待SID 146。SID 146持有1个排他锁(LMODE=6),而SID 144请求以共享模式获得该锁(REQUEST=4)。

除此之外,SID 144自身还持有1个排他锁(LMODE=6)。

这种情况很类似具有唯一索引的情况。

同样查看SID 144正在等待的对象:

DBA用户查看:

select ROW_WAIT_OBJ#,

ROW_WAIT_FILE#,

ROW_WAIT_BLOCK#,

ROW_WAIT_ROW#

from v$session

where sid=144;

ROW_WAIT_OBJ# ROW_WAIT_FILE# ROW_WAIT_BLOCK# ROW_WAIT_ROW#

------------- -------------- --------------- -------------

54482              0               0             0

SID 144等待的对象号是54482,但没有其他信息,通过对象号查找到等待是该表上的位图索引:

select owner,object_name,object_type from dba_objects where object_id=54482;

OWNER      OBJECT_NAME          OBJECT_TYPE

---------- -------------------- --------------------

LDY        TX_EG_BITMAP         INDEX

考虑到是否位图索引只锁住一部分,于是增加做了以下4个实验:

SQL> select * from tx_eg;

ID NAME       SEX

---------- ---------- ----------

10 Xiongwh    MALE

1 liaowh     MALE

2 liaody     MALE

3 wanghh     MALE

4 zhangxx    FEMALE

5 linjx      MALE

实验1:

Ses#1:  FEMALE->MALE

Ses#2:  MALE->FEMALE

Ses#1:  update tx_eg set sex='MALE' where id=4;

Ses#2:  update tx_eg set sex='FEMALE' where id=3;

实验1结果:需要等待。

实验2:

Ses#1:  MALE->MALE

Ses#2:  MALE->FEMALE

Ses#1:  update tx_eg set sex='MALE' where id=2;

Ses#2:  update tx_eg set sex='FEMALE' where id=3;

实验2结果:不会等待,2个session都可以update。

实验3:

Ses#1:  MALE->FEMALE

Ses#2:  MALE->MALE

Ses#1:  update tx_eg set sex='FEMALE' where id=2;

Ses#2:  update tx_eg set sex='MALE' where id=3;

实验3结果:不会等待,2个session都可以update。

实验4:

Ses#1:  MALE->FEMALE

Ses#2:  FEMALE->FEMALE

Ses#1:  update tx_eg set sex='FEMALE' where id=3;

Ses#2:  update tx_eg set sex='FEMALE' where id=4;

实验4结果:不会等待,2个session都可以update。

实验结论:只要另一个session需要修改位图索引,则将位图索引的一个位图段锁住,另一个session想要修改位图索引的相同位图段,就必须等待。

transaction缩写为什么是tx_TX Transaction locks常见的4种情况相关推荐

  1. Spring系列第51篇:导致Spring事务失效常见的几种情况

    这算是spring事务第9篇文章了,花了这么多篇文章介绍事务这块的知识,说明事务这块的东西确实比较多.知识点比较细,也非常重要,希望大家能够重视起来,吃透这块的知识. 本文2个目的: 1.使用spri ...

  2. js内存泄漏常见的四种情况(From LeuisKen)

    本文主要选取了4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them 这篇文章中的一小部分来说明一下js中产生内存泄漏的常见情 ...

  3. [摘译]js内存泄漏常见的四种情况

    本文主要选取了4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them 这篇文章中的一小部分来说明一下js中产生内存泄漏的常见情 ...

  4. 如何排查CPU占用过高以及常见的几种情况

    在最近上线过程中遇到cpu占用率过高问题 由于问题已解决,此时仅重现操作方法 1.先用top命令,找到cpu占用最高的进程 PID  如上图 2.再用ps -mp pid -o THREAD,tid, ...

  5. Active Spring transaction synchronization or active JTA transaction with specifi

    1,写了一个保存日志方法,在无事务方法体里执行. 2,使用hibernate的save方法保存时报错 java.lang.IllegalStateException: Active Spring tr ...

  6. 常见的几种视频和音频格式

    视频格式一般分为影像格式(Video Format)和流格式(Stream Video Format) 一.影像格式 1.AVI格式 (audio video interleaved) 播放软件:(W ...

  7. 常见的几种ADSL 路由器的端口映射方法

    ==大亚科技 DB-108路由器的端口映射方法 大亚108全攻略(路由设置方法,端口映射方法) 一.路由设置方法: 1.先硬件连接,现在的交换机没有UPLINK口了确认正确与否:看设备的PC指示灯是否 ...

  8. 现今最常见的若干种语言

    某些语言的发展历史(和它的总体能力)很有意思.以下描述了现今最常见的若干种语言. Ada是一种通用的高级编程语言,基于Pascal.它的开发受到美国国防部的资助,尤其适合实时及嵌入式系统.Ada强调数 ...

  9. 【JS语法糖】常见的几种JS语法糖

    [JS语法糖]常见的几种JS语法糖 今天遇到一个前端方面的新词汇 语 法 糖 第一次听到这个词 我的第一反应是:这是一个 糖 可能是像这样的: 或者 像这样: [PS:旺仔牛奶是不是该给我打钱了 ? ...

最新文章

  1. Yahoo为啥赚不到钱
  2. (二十)java多线程之ScheduledThreadPoolExecutor
  3. 多层 UIScrollView 嵌套滚动解决方案
  4. 16-垃圾回收相关概念
  5. Visual Studio 智能提示消失解决办法
  6. PHP替换回车换行的三种方法
  7. 关于IE6.7.8.FF兼容的问题
  8. leetcode-187-重复的DNA序列
  9. 二维数组作为形参,传递二维数组的值
  10. maven项目乱码以及项目名出现红叉
  11. Ibatis SqlMapclient对象
  12. 前端面试之浏览器安全
  13. 经济统计学专业学C语言,经济统计学专业有哪些课程
  14. excel锁定单元格不能修改_锁定单元格不被任意修改和删除
  15. vscode自动加前缀_史上最全vscode配置使用教程
  16. 编写.CHM格式的文档
  17. 桂林理工大学 程序设计实践课程 实习报告
  18. [生存志] 第37节 幽王烽火戏诸侯
  19. aspen压缩因子_Aspen 物性代号及常用的英语单词中英文对照
  20. WZOI-261疯狂吃鸡腿2

热门文章

  1. Eclipse搭建SSH环境实现Struts2分页显示mysql数据库表中内容
  2. Amoeba-mysql开源项目高可用读写分离
  3. 保持 Go 模块兼容
  4. Linux 命令(84)—— id 命令
  5. Oracle 索引失效的六大限制条件
  6. Hadoop平台搭建
  7. 为什么不能在scrollview中直接添加一个image,然后使animation.begin()??
  8. 和root权限挣扎过的一些记录
  9. Linux之mkdir命令
  10. 2018年最受欢迎的Python库,你都用过吗?