DML锁之间的相容关系以及实验

主要讲DML锁之间的相容关系以及一些实验:

DML锁主要分:行级锁和表级锁

行级锁

行级锁(TX锁):即事务锁,当事务进行insert,update,delete以及使用select ..for update语句时会获取到一个TX锁,直至事务结束(commit或者rollback)该锁才被释放。

在每个数据块的头部都有一个ITL(相关事务列表),当一个事务需要修改数据块中的数据(insert,update,delete以及使用select ..for update)时,ITL会将该数据块的事务记录在ITL中的一项(即slot)中。

数据块中的项数由数据块所在表定义中的INITRANSMAXTRANS参数所决定

 

表级锁

表级锁(TM锁)

在给表加锁时,一方面要检查申请加的锁是否和与原有的表级锁相容;另一方面还要检查该锁是否与该表中的每一行上的锁是否相容;在进行第而个检查时会带来一定的性能问题。所以引入意向锁

1、  意向锁指:如果对一个节点加意向锁,则需要指明该节点的下一层正在被加的锁。也就是说对任意一个节点加锁时,都需要在其上一层节点加意向锁。比如:当对表中一行记录加锁时,先对行所在的表加意向锁,然后再对该行加锁。

2、  意向锁的类型:

意向共享锁(IS锁):给某个节点加IS锁,那么该节点的下层节点意向加S锁;

意向排它锁(IX锁):给某个节点加IX锁,那么该节点的下层节点意向加X锁;

基本锁类型(X锁,S锁)与意向锁(IS锁,IX锁)组合有:S+ISS+IXX+ISX+IX,其中S+ISS+IXX+ISX+IX组合锁并没有使锁对其他锁的排斥程度(即锁的强度)提高,所以S+IX该组合锁很特殊,提高了锁的强度。

所以将数据库中的表级锁的模式有:SXISIXSIX,对应与通常所说的SXRSRXSRX

3、  加锁和解锁的顺序:

加锁顺序:自上层向下层方向进行加锁;

解锁顺序:自下层向上层方向给解锁;

 

1:数据库中TM锁的相容距阵

             T2        T1

S

X

RS

RX

SRX

S

Y

N

Y

N

N

X

N

N

N

N

N

RS

Y

N

Y

Y

Y

RX

N

N

Y

Y

N

SRX

N

N

Y

N

N

 

 2 TM锁的小结:

SQL语句

表锁模式

 允许的表锁模式

Select …from table…

none

RSRXSSRXX

Insert into table…

RX

RSRX

Update table …

RX

RSRX

Delete from table …

RX

RSRX

Selete …from table for update of …

RS

RSRXSSRX

Lock table table in row share mode

RS

RSRXSSRX

Lock table table in row exclusive mode

RX

RSRX

Lock table table in share mode

S

RSS

Lock table table in share row exclusive mode

SRX

RS

Lock table table in exclusive mode

X

 

注:通常进行的DML操作(insert,update,delete以及使用select ..for update),在表级所获得的锁只是意向锁(RS或者RX锁),真正的封锁粒度还是在行级。

 

首先将一些用到监控数据库锁的脚本写出如下:

1showlock.sql:通过连接v$locked_object,all_objects两个视图,显示哪些对象被哪些会话锁住

/* showlock.sql*/

column o_name format a10

column lock_type format a20

column object_name format a15

select rpad(oracle_username,10) o_name,

       session_id sid,

       decode(locked_mode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_type,

       object_name,xidusn,xidslot,xidsqn

  from v$locked_object,all_objects

 where v$locked_object.OBJECT_ID=all_objects.object_id;

 

 2showalllock.sql:主要显示当前所有TMTX锁的信息

/* showalllock.sql*/

select sid,type,id1,id2,

       decode(LMODE,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_type,

       request,ctime,block

 from  v$lock

where Type in ('TM','TX');

 

实验如下:

--在外键上没有建索引的子表

CREATE TABLE emp

   (emp_id number(10),

    name varchar2(20) ,

    dept_id number(2) CONSTRAINT fk_emp

                      references dept(dept_id)

                      ON DELETE CASCADE 

   );

 

--在外键上有建索引的子表

CREATE TABLE emp1

   (emp_id number(10),

    name varchar2(20) ,

    dept_id number(2) CONSTRAINT fk_emp1

                      references dept(dept_id)

                      ON DELETE CASCADE 

   );

-- Create/Recreate indexes  on the Foreign Key

create index EMP1_DEPT_ID on EMP1 (DEPT_ID);

 

alter table emp add (constraint pk_emp primary key (emp_id)); 

alter table emp1 add (constraint pk_emp1 primary key (emp_id)); 

 

 

insert into dept values (10,'ACCOUNTING'); 

insert into dept values (11,'SALES'); 

insert into dept values (12,'RESEARCH'); 

insert into dept values (14,'TT');

 

insert into emp values (2001,'Jason',10); 

insert into emp values (2002,'Mike',11); 

insert into emp values (2003,'Green',12); 

insert into emp values (2004,'Grey',10); 

 

insert into emp1 values (2001,'Jason',10); 

insert into emp1 values (2002,'Mike',11); 

insert into emp1 values (2003,'Green',12); 

insert into emp1 values (2004,'Grey',10); 

 

实验1

会话1中:

Daimin用户下的三个会话会话1,会话2,会话3,会话5sys用户下的会话4

SQL> insert into dept(dept_id,name) values(15,'daimin');

1 row inserted

 

会话4中查看锁信息:

SQL> @c:/showlock.sql

O_NAME           SID LOCK_TYPE       OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN

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

DAIMIN            142 Row share            EMP1                    20         36        498

DAIMIN            142 Row Exclusive        DEPT                     20          36        498

DAIMIN            142 Row share            EMP                     20         36        498

 

SQL> @c:/showalllock.sql;

       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK

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

       142 TM        55606          0 Row Exclusive                  0        297          0 –----dept表的表锁

       142 TX      1310756         498 Exclusive                     0        297          0  –----dept表的行锁

       142 TM        55614          0 Row share                     0        297          0

       142 TM        55612          0 Row share                     0        297          0

 

在会话2中:

对子表进行更新操作:

SQL> update emp set name='daimin' where emp_id=2004;

1 row updated

 

会话4中查看锁信息:

SQL> @c:/showlock.sql

O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN

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

DAIMIN            132 Row Exclusive        EMP                     12         10        658

DAIMIN            142 Row share            EMP                     20         36        498

DAIMIN            142 Row Exclusive        DEPT                     20          36        498

DAIMIN            142 Row share            EMP1                    20         36        498

 

SQL> @c:/showalllock.sql;

       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK

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

       132 TX       786442        658 Exclusive                     0         66          0  --emp表的行级缩

       132 TM        55612          0 Row Exclusive                 0         66          0

       142 TX      1310756        498 Exclusive                     0        792          0

       142 TM        55612          0 Row share                     0        792          0

       142 TM        55606          0 Row Exclusive                 0        792          0

       142 TM        55614          0 Row share                     0        792          0

分析:在父表都被插入操作时,子表上被加了表级锁RS锁,当对子表进行更新操作时,对子表需要申请一个表级锁RX锁,由于RS锁和RX锁是相容的,所以这两个事务并不相互阻塞。

 

会话3中:

对子表加一个排它锁(X锁):

SQL>  lock table emp in exclusive mode;

此时发现事务处于阻塞状态。

 

在会话4中查看锁信息:

SQL> @c:/showlock.sql

O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN

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

DAIMIN            132 Row Exclusive        EMP                     12         10        658

DAIMIN            139 None                 EMP                      0          0          0

DAIMIN            142 Row share            EMP                     20         36        498

DAIMIN            142 Row Exclusive        DEPT                     20          36        498

DAIMIN            142 Row share            EMP1                    20         36        498

 

SQL> @c:/showalllock.sql;

       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK

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

       132 TM        55612          0 Row Exclusive                 0        642          1

       132 TX       786442        658 Exclusive                     0        642          0

       139 TM        55612          0 None                          6         69          0

       142 TM        55614          0 Row share                     0       1368          0

       142 TX      1310756        498 Exclusive                     0       1368          0

       142 TM        55612          0 Row share                     0       1368          1

       142 TM        55606          0 Row Exclusive                 0       1368          0

分析:从锁信息可以看出,会话3中的事务连TM锁(EMP表级锁)都没有获取得到,所以更不会获取得到行级锁,因为加锁的方向是自上层向下层方向进行的,也就是说是先加TM表级锁,然后再给加行级锁。主要原因是由于申请需要加的X锁与当前EMP表中的RX锁以及RS锁不相容,所以拒绝了X锁的申请,导致该事务受阻塞。

 

会话5中:

SQL> update emp set name='daimin' where emp_id=2004;

该事务也被阻塞

 

在会话4中查看锁信息:

SQL> @c:/showlock.sql

O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN

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

DAIMIN            132 Row Exclusive        EMP                     12         10        658

DAIMIN            139 Row Exclusive        EMP                      0          0          0 获取到RX表级缩

DAIMIN            142 Row share            EMP                     20         36        498

DAIMIN            142 Row Exclusive        DEPT                     20          36        498

DAIMIN            142 Row share            EMP1                    20         36        498

 

SQL> @c:/showalllock.sql;

       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK

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

       132 TM        55612          0 Row Exclusive                 0       2019          0

       132 TX       786442        658 Exclusive                     0       2019          1

       139 TX       786442        658 None                          6         18    0 –没有获取到EMP的行级锁

       139 TM        55612          0 Row Exclusive                 0         18      0 ----获取到EMP表的表级锁

       142 TX      1310756        498 Exclusive                     0       2745          0

       142 TM        55612          0 Row share                     0       2745          0

       142 TM        55606          0 Row Exclusive                 0       2745          0

       142 TM        55614          0 Row share                     0       2745          0

分析:从上面的锁信息中可以看出,由于会话5EMP表加RX锁,由于原来EMP表中存在的RXRS锁是与RX锁相容的,所以对会话5EMP表加RX表级锁是成功的。但是,

由于会话5中的事务申请获取EMP表的锁的所在行正好与会话2中事务中更新的行一样,由于会话2中的事务还没有释放,所以对emp_id=2004的行记录已经被会话2事务独占并且对该行加有TX锁,所以此时会话5也申请获取emp_id=2004记录的TX行锁必须等待,等会话2的事务结束,释放对emp_id=2004行的TX锁会话5才能加TX锁。

会话6中:在会话1和会话2基础上更新父节点:

update dept set name=name where dept.dept_id=12;

 

在会话4中查看锁信息:

SQL> @c:/showlock.sql

O_NAME            SID LOCK_TYPE            OBJECT_NAME         XIDUSN    XIDSLOT     XIDSQN

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

DAIMIN            132 Row Exclusive        EMP                     12         19        658

DAIMIN            133 Row Exclusive        DEPT                    18           3        669

DAIMIN            142 Row share            EMP                     20         36        498

DAIMIN            142 Row Exclusive        DEPT                     20          36        498

DAIMIN            142 Row share            EMP1                    20         36        498

 

SQL> @c:/showalllock.sql;

       SID TYPE        ID1        ID2 LOCK_TYPE               REQUEST      CTIME      BLOCK

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

       132 TM        55612          0 Row Exclusive                 0         21          0

       132 TX       786451        658 Exclusive                     0         21          0

       133 TX      1179651        669 Exclusive                     0         12          0

       133 TM        55606          0 Row Exclusive                 0         12          0

       142 TM        55614          0 Row share                     0       4719          0

       142 TX      1310756        498 Exclusive                     0       4719          0

       142 TM        55612          0 Row share                     0       4719          0

       142 TM        55606          0 Row Exclusive                 0       4719          0

分析:原来DEPT表上存在的锁有RX锁,由于RX锁与RX锁是相容的,所以当对DEPT表做更新时不受阻塞。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值