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

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想要修改位图索引的相同位图段,就必须等待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值