MLDN
课程咨询[孔老师]QQ 1031143579孔老师QQ课程咨询留言 课程咨询[徐老师 ]QQ 945313230
徐老师QQ课程咨询留言
课程咨询[刘老师 ]QQ 514543793
刘老师QQ课程咨询留言
java培训
北京java培训
IT电子教育门户 高端JAVA培训 -=> 资源中心 -=> 数据库 -=> Oracle 9i/10g -=> 正文

Oracle多粒度封锁机制研究(二)

 发布日期:2009-3-4 8:58:00 发布者:[IT电子教育门户]   评论:[]  浏览:

1.1.1v$locked_object视图

    v$locked_object视图列出当前系统中哪些对象正被锁定,其主要字段说明如下:

字段名称
 类型
 说明
 
XIDUSN
 NUMBER
 回滚段号;
 
XIDSLOT
 NUMBER
 槽号;
 
XIDSQN
 NUMBER
 序列号;
 
OBJECT_ID
 NUMBER
 被锁对象标识;
 
SESSION_ID
 NUMBER
 持有锁的会话(SESSION)标识;
 
ORACLE_USERNAME
 VARCHAR2(30)
 持有该锁的用户的Oracle用户名;
 
OS_USER_NAME
 VARCHAR2(15)
 持有该锁的用户的操作系统用户名;
 
PROCESS
 VARCHAR2(9)
 操作系统的进程号;
 
LOCKED_MODE
 NUMBER
 锁模式,取值同表三中的LMODE;
 


表五:v$locked_object视图字段说明

    1.2监控脚本

    根据上述系统视图,可以编制脚本来监控数据库中锁的状况。

    1.2.1showlock.sql

    第一个脚本showlock.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;
 


    1.2.2showalllock.sql

    第二个脚本showalllock.sql,该脚本主要显示当前所有TM、TX锁的信息;

/* 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('TX','TM');
 


    2Oracle多粒度封锁机制示例

    以下示例均运行在Oracle 8.1.7上,数据库版本不同,其输出结果也可能有所不同。首先建立3个会话,其中两个(以下用SESS#1、SESS#2表示)以SCOTT用户连入数据库,以操作Oracle提供的示例表(DEPT、EMP);另一个(以下用SESS#3表示)以SYS用户连入数据库,用于监控;

    2.1操作同一行数据引发的锁阻塞

SESS#1:

SQL> select * from dept for update;

DEPTNO DNAMELOC

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

10 account70

20 research8

30 sales8

40 operations8

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT17 Row shareDEPT 825861

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

17 TX5242905861 Exclusive07610

17 TM329700 Row share07610
 


    如第一个脚本showlock所示,执行完SELECT…FOR UPDATE语句后,SESS#1(SID为17)在DEPT表上获得Row share锁;如第二个脚本showalllock所示,SESS#1获得的TX锁为Exclusive,这些都验证了上面的理论分析。另外,我们可以将TX锁的ID1按如下方法进行分解:

SQL> select trunc(524290/65536) xidusn,mod(524290,65536) xidslot from dual;

XIDUSN XIDSLOT

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

82
 


    分解结果与第一个脚本直接查出来的XIDUSN与XIDSLOT相同,而TX锁的ID2(5861)与XIDSQN相同,可见当LOCK TYPE为TX时,ID1实际上是该事务所占用的回滚段段号与事务表中的槽(SLOT)号的组合,ID2即为该槽被重用的次数,而这三个值实际上可以唯一地标识一个事务,即TRANSACTION ID,这三个值从系统表v$transaction中也可查到。

    另外,DEPT表中有4条记录被锁定,但TX锁只有1个,这也与上面的理论分析一致。继续进行操作:

SESS#2:

SQL> update dept set loc=loc where deptno=20;
 


    该更新语句被阻塞,此时再查看系统的锁情况:

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT17 Row shareDEPT 825861

SCOTT19 Row ExclusiveDEPT 000

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

17 TX5242905861 Exclusive034621

17 TM329700 Row share034620

19 TM329700 Row Exclusive070

19 TX5242905861 None670
 


    在DEPT表上除了SESS#1(SID为17)持有Row share锁外,又增加了SESS#2(SID为19)持有的Row Exclusive锁,但还没有为SESS#2分配回滚段(XIDUSN、XIDSLOT、XIDSQN的值均为0);而从第二个脚本看到,SESS#2的TX锁的LOCK_TYPE为None,其申请的锁类型(REQUEST)为6(即Exclusive),而其ID1、ID2的值与SESS#1所持有的TX锁的ID1、ID2相同,SESS#1的TX锁的阻塞域(BLOCK)为1,这就说明了由于SESS#1持有的TX锁,阻塞了SESS#2的更新操作(SESS#2所更新的行与SESS#1所锁定的行相冲突)。还可以看出,SESS#2先申请表级的TM锁,后申请行(事务)级的TX锁,这也与前面的理论分析一致。
下面,将SESS#1的事务进行回滚,解除对SESS#2的阻塞,再对系统进行监控。

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT19 Row ExclusiveDEPT 2105803

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

19 TX1310825803 Exclusive01570

19 TM329700 Row Exclusive03330
 


    可以看到,SESS#1的事务所持有的锁已经释放,系统为SESS#2的事务分配了回滚段,而其TX锁也已经获得,并且ID1、ID2是其真正的Transaction ID.再将会话2的事务进行回滚。

SESS#2:

SQL> rollback;

Rollback complete.
 


    检查系统锁的情况:

SESS#3:

SQL> @showlock

no rows selected

SQL> @showalllock

no rows selected
 


    可以看到,TM与TX锁已全部被释放。

    2.2实体完整性引发的锁阻塞

    DEPT(部门)表有如下字段DEPTNO(部门编号),DNAME(部门名称),LOC(部门位置);其中DEPTNO列为主键。

SESS#1

SQL> INSERT INTO DEPT(DEPTNO) VALUES(50);

1 row created.

SESS#3

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT7 Row ExclusiveDEPT 68829

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TX39330429 Exclusive060

7 TM35740 Row Exclusive060
 


    向DEPT表中插入一条DEPTNO为50的记录后,SESS#1(SID为7)在DEPT表上获得Row Exclusive锁,并且由于进行了数据插入,该事务被分配了回滚段,获得TX锁。

SESS#2

INSERT INTO DEPT(DEPTNO) VALUES(50);
 


    这时,SESS#2(SID为8)也向DEPT表中插入一条DEPTNO为50的记录,该语句被阻塞,检查锁情况:

SESS#3

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT8 Row ExclusiveDEPT 77530

SCOTT7 Row ExclusiveDEPT 68829

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TX39330429 Exclusive0921

7 TM35740 Row Exclusive0920

8 TX45882730 Exclusive0220

8 TM35740 Row Exclusive0220

8 TX39330429 None4220
 


    SESS#2在DEPT表上也获得了Row Exclusive锁,同样也获得了回滚段的分配,得到TX锁,但是由于其插入的记录与SESS#1插入的记录的DEPTNO均为50,该语句成功与否取决于SESS#1的事务是提交还是回滚,所以SESS#2被阻塞,表现为SESS#2以Share方式(REQUEST=4)等待SESS#1所持有的TX锁的释放。

    这时,如果SESS#1进行回滚:

SESS#1

SQL> ROLLBACK;

Rollback complete.

SESS#2

1 row created.

SESS#3

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT8 Row ExclusiveDEPT 77530

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

8 TX45882730 Exclusive01360

8 TM35740 Row Exclusive01360
 


    SESS#2的阻塞将被解除,SESS#2只持有原先已有的TM与TX锁,其等待的TX锁(由SESS#1持有)也消失了。

    如果SESS#1提交而不是回滚,在SESS#2上将会出现如下提示:

    ERROR at line 1:

    ORA-00001: unique constraint (SCOTT.PK_DEPT) violated错误。

    即发生主键冲突,SESS#1与SESS#2的所有锁资源均被释放。
 2.3参照完整性引发的锁阻塞

    EMP(员工)表有如下字段:EMPNO(员工编号),ENAME(员工姓名),DEPTNO(员工所在部门编号),其中DEPTNO列为外键,其父表为DEPT.

SESS#1

SQL> insert into dept(deptno) values(60);

1 row created.

SESS#3

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT7 Row ExclusiveDEPT 2633

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TX13107833 Exclusive01480

7 TM35740 Row Exclusive01480
 


    SESS#1(SID为7)在DEPT表中先插入一条DEPTNO为60的记录,SESS#1获得了DEPT表上的Row Exclusive锁,及一个TX锁。

SESS#2

insert into emp(empno,deptno) values(2000,60);

被阻塞

SESS#3

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT7 Row ExclusiveDEPT 2633

SCOTT8 Row ExclusiveEMP32031

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TX13107833 Exclusive02281

7 TM35740 Row Exclusive02280

8 TX19662831 Exclusive090

8 TM35760 Row Exclusive090

8 TX13107833 None490
 


    SESS#2(SID为8)向EMP表中出入一条新记录,该记录DEPT值为60(即SESS#1刚插入,但还未提交的记录的DEPTNO值),SESS#2获得了EMP表上的Row Exclusive锁,另外由于插入记录,还分配了回滚段及一个TX锁,但由于SESS#2的插入语句是否成功取决于SESS#1的事务是否进行提交,所以它被阻塞,表现为SESS#2以Share(REQUEST=4)方式等待SESS#1释放其持有的TX锁。这时SESS#1如果提交,SESS#2的插入也将执行成功,而如果SESS#1回滚,由于不符合参照完整性,SESS#2将报错:

SESS#2

insert into emp(empno,deptno) values(2000,60)

*

ERROR at line 1:

ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated - parent key not

Found
 


    SESS#2持有的锁也被全部释放。
 2.4外键未加索引引发的锁阻塞

    EMP表上的DEPTNO列为外键,但没有在该列上建索引。

SESS#1

SQL> delete emp where 0=1;

0 rows deleted.

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT7 Row ExclusiveEMP000

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TM35760 Row Exclusive0100
 


    首先SESS#1(SID为7)做了一个删除操作,但由于条件(0=1)为永假,所以实际上并没有一行被删除,从监控脚本可以看出SESS#1在EMP表上获得Row Exclusive锁,但由于没有实际的行被删除,所以并没有TX锁,也没有为SESS#1分配回滚段。

    SESS#2:

    SQL> delete dept where 0=1;
 


    该语句虽然也不会删除实际数据,但却被阻塞,查看系统的锁情况:

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT8 NoneEMP000

SCOTT7 Row ExclusiveEMP000

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TM35760 Row Exclusive0311

8 TM35760 None4120
 


    SESS#2申请在EMP表上加SHARE锁(REQUEST=4),但该申请被SESS#1阻塞,因为SESS#1已经在EMP表上获得了Row Exclusive锁,与SHARE锁不相容。

    下面我们对SESS#1进行回滚后,再进行监控。

SESS#3:

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT8 ShareEMP000

SCOTT8 Row ExclusiveDEPT 000

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

8 TM35740 Row Exclusive0160

8 TM35760 Share0160
 


    SESS#2在EMP表上获得Share锁后,又在DEPT表上获得Row Exclusive锁,由于没有实际的行被修改,SESS#2并没有获得TX锁。

    在Oracle8中,如果子表的外键上没有加索引,当在父表上删除记录时,会先在子表上申请获得Share锁,之后再在父表上申请Row Exclusive锁。由于表级Share锁的封锁粒度较大,所以容易引起阻塞,从而造成性能问题。

    当在外键上建立索引后,在父表上删除数据将不再对子表上加Share锁,如下所示:

SESS#1:

SQL> create index i_emp_deptno on emp(deptno);

Index created.

SQL> delete dept where 0=1;

0 rows deleted.

SQL>

SQL> @showlock

O_NAMESID LOCK_TYPEOBJECT_NAMEXIDUSN XIDSLOT XIDSQN

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

SCOTT7 Row ExclusiveDEPT 000

SQL> @showalllock

SID TYID1ID2 LOCK_TYPEREQUESTCTIMEBLOCK

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

7 TM35740 Row Exclusive090
 


    可以看到,在EMP表DEPTNO列上建立索引后,在DEPT表上执行DELETE操作,不再要求在EMP表上加Share锁,只是在DEPT表上加Row Exclusive锁,封锁的粒度减小,引起阻塞的可能性也减小。

    3Oracle多粒度封锁机制总结

    Oracle通过具有意向锁的多粒度封锁机制进行并发控制,保证数据的一致性。其DML锁(数据锁)分为两个层次(粒度):即表级和行级。通常的DML操作在表级获得的只是意向锁(RS或RX),其真正的封锁粒度还是在行级;另外,在Oracle数据库中,单纯地读数据(SELECT)并不加锁,这些都极大地提高了系统的并发程度。

    在支持高并发度的同时,Oracle利用意向锁及数据行上加锁标志位等设计技巧,减小了Oracle维护行级锁的开销,使其在数据库并发控制方面有着明显的优势。

java视频教程
JAVA核心_75对象序列化练习
 JAVA核心_75对象序列化..
JAVA核心_74对象序列化
 JAVA核心_74对象序列化..
JAVA核心_73字符编码
 JAVA核心_73字符编码 ..
JAVA核心_72Scanner
 JAVA核心_72Scann..
JAVA核心_71 IO练习 二
 JAVA核心_71 IO练习..
相关文章 推荐文章
详解Oracle的几种分页查询语..[4.13]
简述Oracle数据仓库的体系结..[4.3]
Oracle中OSFA和数据仓库..[3.23]
使用度量基线技术实现Oracle..[3.23]
Oracle多粒度封锁机制研究(..[3.4]
详解Oracle的几种分页查询语句
简述Oracle数据仓库的体系结构
如何从完好的数据文件恢复oracle数..
选择合适的数据库关闭方法
Oracle中OSFA和数据仓库简介
热门文章
详解Oracle的几种分页查询语句
oracle中的数据库乱码的原因与解决..
ORACLE索引与高性能SQL介绍
Oracle 数据库的备份与恢复
如何从完好的数据文件恢复oracle数..
oracle-快速删除重复的记录
Oracle 10g的安装步骤和注意事..
Oracle(三)
Oracle 10g RAC之网络设置..
Oracle中操作语句和控制语言解析
今日更新
详解Oracle的几种分页查询语句
简述Oracle数据仓库的体系结构
如何从完好的数据文件恢复oracle数..
选择合适的数据库关闭方法
Oracle中OSFA和数据仓库简介
使用度量基线技术实现Oracle自我监..
Oracle多粒度封锁机制研究(二)
Oracle多粒度封锁机制研究(一)
Oracle数据库段管理有技巧
Oracle Data block 的..
JAVA招聘网
 评一评
正在读取…
  姓名:
  评论:
    
【注】 发表评论必需遵守以下条例: !!!
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
关于我们 | 商务合作 | 招聘信息 | 客服中心 | 服务条款 | 免责声明 | 网站导航 QQ留言
Copyright 2009 魔乐培训MLDN.CN all rights reserved 版权所有 京ICP备07008611号