Oracle数据库之【锁】Oracle锁系列
小标 2018-08-22 来源 : 阅读 1010 评论 0

摘要:本文主要向大家介绍了Oracle数据库之【锁】Oracle锁系列,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助。

本文主要向大家介绍了Oracle数据库之【锁】Oracle锁系列,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助。1  BLOG文档结构图

2  前言部分
2.1  导读和注意事项
各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:
① 锁的概念、分类、及其模拟
② 查询锁的视图及视图之间的关联
③ 锁的参数(DML_LOCKS、DDL_LOCK_TIMEOUT)
④ FOR UPDATE及FOR UPDATE OF系列
⑤ 带ONLINE和不带ONLINE创建索引的锁情况(是否阻塞DML操作)
⑥ 包或存过不能编译的解决方法
⑦ ORA-08104解决方法
Tips:
① 本文在itpub(//blog.itpub.net/26736162)、博客园(//www.cnblogs.com/lhrbest)和微信公众号(xiaomaimiaolhr)上有同步更新。
② 文章中用到的所有代码、相关软件、相关资料及本文的pdf版本都请前往小麦苗的云盘下载,小麦苗的云盘地址见://blog.itpub.net/26736162/viewspace-1624453/。
③ 若网页文章代码格式有错乱,请下载pdf格式的文档来阅读。
④ 在本篇BLOG中,代码输出部分一般放在一行一列的表格中。其中,需要特别关注的地方我都用灰色背景和粉红色字体来表示,比如在下边的例子中,thread 1的最大归档日志号为33,thread 2的最大归档日志号为43是需要特别关注的地方;而命令一般使用黄色背景和红色字体标注;对代码或代码输出部分的注释一般采用蓝色字体表示。




  List of Archived Logs in backup set 11
  Thrd Seq     Low SCN    Low Time            Next SCN   Next Time
  ---- ------- ---------- ------------------- ---------- ---------
  1    32      1621589    2015-05-29 11:09:52 1625242    2015-05-29 11:15:48
  1    33      1625242    2015-05-29 11:15:48 1625293    2015-05-29 11:15:58
  2    42      1613951    2015-05-29 10:41:18 1625245    2015-05-29 11:15:49
  2    43      1625245    2015-05-29 11:15:49 1625253    2015-05-29 11:15:53
[ZHLHRDB1:root]:/>lsvg -o
T_XLHRD_APP1_vg
rootvg
[ZHLHRDB1:root]:/> 
00:27:22 SQL> alter tablespace idxtbs read write;
====》2097152*512/1024/1024/1024=1G 




本文如有错误或不完善的地方请大家多多指正,ITPUB留言或QQ皆可,您的批评指正是我写作的最大动力。
 
2.2  本文简介
有网友一直催着说发一些锁系列的文章,其实小麦苗一直对锁这块也没有彻底去研究过,今年写书里边写到了锁的内容,干脆就彻底把这一块整理了一下,现在分享给大家,若有错误,还请大家及时指正。
文章很多内容来源于网络或Concepts的内容,若有侵权还请联系小麦苗删除。
第二章 锁
2.1  锁的基本概念
 
锁的定义:锁(lock)机制用于管理对共享资源的并发访问,用于多用户的环境下,可以保证数据库的完整性和一致性。锁是防止访问相同资源的事务之间的破坏性交互的机制。既可以是用户对象(例如表或行),也可以是对用户不可见的系统对象(例如共享数据结构和数据字典行)。
锁的解释:当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的完整性和一致性。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制。
锁的作用:在并发事务之间防止破坏性的交互作用,不需要用户的动作,自动使用最低的限制级别,在事务处理期间保持。
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
锁(lock)是防止访问相同资源(例如表或数据行等用户对象,或内存中的共享数据结构及数据字典等对用户不可见的系统对象)的事务产生破坏性交互的机制。
在任何情况下,Oracle 都能够自动地获得执行 SQL 语句所必须的所有锁,无需用户干预。Oracle 会尽可能地减少锁产生的影响,从而最大程度地保证数据的并发访问能力,并确保数据一致性及错误恢复。同时,Oracle 也支持用户手工加锁的操作。
Oracle 从来不会升级锁,但是它会执行锁转换(lock conversion)或锁提升(lock promotion)。
A lock is a mechanism that prevents destructive interactions, which are interactions that incorrectly update data or incorrectly alter underlying data structures, between transactions accessing shared data. Locks play a crucial row in maintaining database concurrency and consistency.
锁是一种机制,用来防止多个共同访问共享数据的事务之间的破坏性交互,包括不正确地更新数据或不正确地更改基础数据结构。锁在维护数据库并发性和一致性当中扮演着一个关键的角色。
 
2.1.1  并发和并行
并发(concurrency)和并行(parallel)。并发意思是在数据库中有超过两个以上用户对同样的数据做修改,而并行的意思就是将一个任务分成很多小的任务,让每一个小任务同时执行,最后将结果汇总到一起。所以说,锁产生的原因就是并发,并发产生的原因是因为系统和客户的需要。
 
2.1.2  使用锁
在单用户数据库中,锁不是必需的,因为只有一个用户在修改信息。但是,当多个用户在访问和修改数据时,数据库必须提供一种方法,以防止对同一数据进行并发修改。锁实现了以下重要的数据库需求:
v ·一致性
一个会话正在查看或更改的数据不能被其它会话更改,直到用户会话结束。
v ·完整性
数据和结构必须按正确的顺序反映对他们所做的所有更改。数据库通过其锁定机制,提供在多个事务之间的数据并发性、一致性、和完整性。锁定将自动执行,并且不需要用户操作。
执行SQL语句时,Oracle数据库自动获取所需的锁。例如,在数据库允许某个会话修改数据之前,该会话必须先锁定数据。锁给予该会话对数据的独占控制权,以便在释放该锁之前,任何其它事务都不可以修改被锁定的数据。
因为数据库的锁定机制与事务控制紧密地绑定在一起,应用程序设计人员只需要正确地定义事务,而数据库会自动管理锁定。
 
2.1.3  锁模式(Lock Modes)--共享和排它
Oracle数据库自动使用最低适用的限制级别,来提供最高程度的数据并发,但还能提供非常安全的数据完整性。限制级别越低、则有更多的可用数据供其他用户访问。相反,限制级别越高,则其它事务为获取其所需的锁类型就将遭受更多的限制。
在多用户的数据库系统中,Oracle使用两种模式的锁:
 
2.1.4  锁的持续时间
事务内各语句获得的锁在事务执行期内有效,以防止事务间破坏性的相互干扰,例如:脏读取(dirty read),无效地更新(lost update),以及其它并发事务中具有破坏性的 DDL 操作。如果某个事务中的 SQL 语句对数据进行了修改,只有在此事务提交后开始的事务才能看到前者修改的结果。
当用户提交(commit)或撤销(undo)一个事务后,Oracle 将释放此事务内各个 SQL 语句获得的锁。当用户在事务内回滚到某个保存点(savepoint)后,Oracle 也会释放此保存点后获得的锁。只有当前没有等待被锁资源的事务才能获得可用资源的锁。等待事务不会对可用资源加锁而是继续等待,直至拥有其所等待资源的事务完成提交或回滚。
2.2   显式锁定和隐式锁定
有两种类型:显式锁定和隐式锁定。Oracle锁被自动执行,并且不要求用户干预的锁为隐式锁。对于SQL语句隐式锁是必须的,依赖被请求的动作。隐式锁定除SELECT外,对所有的SQL语句都发生。用户也可以手动锁定数据,这是显式锁定。
隐式锁定:这是Oracle中使用最多的锁。通常用户不必声明要对谁加锁,Oracle 自动可以为操作的对象加锁,这就是隐式锁定。 
显式锁定:用户可以使用命令明确的要求对某一对象加锁。显式锁定很少使用。
 
2.2.1   显式锁定
LOCK TABLE没有触发行锁,只有TM表锁。




LOCK TABLE TABLE_NAME IN ROW SHARE MODE NOWAIT;   --2:RS
LOCK TABLE TABLE_NAME IN SHARE UPDATE MODE;  --2:RS
LOCK TABLE TABLE_NAME IN ROW EXCLUSIVE MODE NOWAIT; --3:RX
LOCK TABLE TABLE_NAME IN SHARE MODE; --4:S
LOCK TABLE TABLE_NAME IN SHARE ROW EXCLUSIVE MODE;  --5:SRX
LOCK TABLE TABLE_NAME IN EXCLUSIVE MODE NOWAIT; --6:X




 
 
2.2.2   隐式锁定
隐式锁定:
Select * from table_name…… 
Insert into table_name……  
Update table_name…… 
Delete from table_name…… 
Select * from table_name for update 
 
 
2.3  悲观锁和乐观锁
 
2.3.1  悲观锁
锁在用户修改之前就发挥作用:
Select ..for update(nowait) 
Select * from tab1 for update 
用户发出这条命令之后,oracle将会对返回集中的数据建立行级封锁,以防止其他用户的修改。 
如果此时其他用户对上面返回结果集的数据进行dml或ddl操作都会返回一个错误信息或发生阻塞。 
1:对返回结果集进行update或delete操作会发生阻塞。 
2:对该表进行ddl操作将会报:Ora-00054:resource busy and acquire with nowait specified. 
原因分析
此时Oracle已经对返回的结果集上加了排它的行级锁,所有其他对这些数据进行的修改或删除操作都必须等待这个锁的释放,产生的外在现象就是其它的操作将发生阻塞,这个这个操作commit或rollback. 
同样这个查询的事务将会对该表加表级锁,不允许对该表的任何ddl操作,否则将会报出ora-00054错误::resource busy and acquire with nowait specified. 
 
会话1:




SYS@lhrdb S1> create table t_lock_lhr as select rownum as id,0 as type from dual connect by rownum <=3;
 
Table created.
 
SYS@lhrdb S1> select * from t_lock_lhr where id=2 and type =0 for update nowait;
 
        ID       TYPE
---------- ----------
         2          0




 
会话2:




SYS@lhrdb S2> select * from t_lock_lhr where id=2 and type=0 for update nowait;
select * from t_lock_lhr where id=2 and type=0 for update nowait
              *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
 
 




 
会话1:




SYS@lhrdb S1> update t_lock_lhr set type=1 where id=2 and type=0;
 
1 row updated.
 
SYS@lhrdb S1> commit;
 
Commit complete.
 
 
SYS@lhrdb S1> select * from t_lock_lhr where id=2;
 
        ID       TYPE
---------- ----------
         2          1
 




 
会话2:




SYS@lhrdb S2> select * from t_lock_lhr where id=2 and type=0 for update nowait;
 
no rows selected
 
 




 
2.3.2  乐观锁
乐观的认为数据在select出来到update进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定,是存在一种可能被其他用户更改的可能。因此Oracle仍然建议是用悲观封锁,因为这样会更安全。 




会话1:
SYS@lhrdb S1> select id,type,ora_rowscn from t_lock_lhr where id = 3;
 
        ID       TYPE ORA_ROWSCN
---------- ---------- ----------
         3          0   37698547
会话2:
SYS@lhrdb S2> select id,type,ora_rowscn from t_lock_lhr where id = 3;
 
        ID       TYPE ORA_ROWSCN
---------- ---------- ----------
         3          0   37698547
会话1:
SYS@lhrdb S1> update t_lock_lhr set type=1 where ora_rowscn=37698547 and id = 3;
 
1 row updated.
 
SYS@lhrdb S1> commit;
 
Commit complete.
SYS@lhrdb S1> select id,type,ora_rowscn from t_lock_lhr where id = 3;
 
        ID       TYPE ORA_ROWSCN
---------- ---------- ----------
         3          1   37698591
会话2:
SYS@lhrdb S2> update t_lock_lhr set type=1 where ora_rowscn=37698547 and id =3;
 
0 rows updated.
 
SYS@lhrdb S2> select id,type,ora_rowscn from t_lock_lhr where id = 3;
 
        ID       TYPE ORA_ROWSCN
---------- ---------- ----------
         3          1   37698591
 




 
 
2.3.3  更新丢失问题的解决方法
更新丢失是指多个用户通过应用程序访问数据库时,由于查询数据并返回到页面和用户修改完毕点击保存按钮将修改后的结果保存到数据库这个时间段(即修改数据在页面上停留的时间)在不同用户之间可能存在偏差,从而最先查询数据并且最后提交数据的用户会把其他用户所作的修改覆盖掉。
解决方法如下:
 
2.4  锁转换和锁升级(Lock Conversion and Escalation)
数据库在必要时执行锁转换。在锁转换中,数据库自动将较低限制的表锁转换为较高限制的其它锁定。一个事务在该事务中所有执行插入、更新、或删除的行上持有行独占锁。因为行锁是在最高程度限制下获得的,因此不要求锁转换,也不执行锁转换。锁转换不同于锁升级,锁升级发生在当某个粒度级别持有许多锁(例如行),数据库将其提高到更高粒度级别(例如表)。如果一个用户锁定了一个表中的许多行,则某些数据库自动将行锁升级到单个表锁。锁的数量减少了,但被锁定的东西却增加了。
Oracle数据库永远不会升级锁。锁升级极大地增加了死锁的可能性。假定一个系统尝试升级事务1中的锁,但因为事务2持有该锁,故不能成功。如果事务2在它可以继续操作之前也需要在相同的数据上进行锁升级,则将发生一个死锁。
ORACLE的锁是block里面实现的,SQLSERVER,DB2是内存里面实现的.内存实现有资源消耗问题,当内存不足会引发锁升级,但是ORACLE不会发生锁升级。
事务拥有在此事务内被插入(insert),更新(update),删除(delete)的数据行的排它行级锁(exclusive row lock)。对于数据行来说,排它行级锁已经是限制程度最高的锁,因此无需再进行锁转换(lock conversion)。
 
2.5  锁的分类
Oracle能够自动地选择不同类型的锁对数据并发访问进行控制,防止用户间破坏性的交互操作。Oracle 将自动地为事务进行锁管理,防止其它事务对需要排它访问的资源执行操作。当事务不再需要加锁的资源并触发某个事件后,锁能够被自动地释放。
在事务执行期间,Oracle 能够根据加锁的资源及需要执行的操作自动地决定锁的类型(types of lock)及对资源的限制级别(level of restrictiveness)。
V$LOCK_TYPE 该视图是对DML锁的类型的解释。
select * from V$LOCK_TYPE v where  v.IS_USER=‘YES‘;
 
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。
在数据行上只有X锁(排它锁)。在Oracle数据库中,当一个事务首次发起一个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行DML语句时,第一个会话在该条记录上加锁,其它的会话处于等待状态。当第一个会话提交后,TX锁被释放,其它会话才可以加锁。
当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致死锁的发生,产生ORA-60的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。
 
 
2.5.1  DML锁(DML Locks)
当Oracle执行DELETE,UPDATE,INSERT,SELECT FOR UPDATE  DML语句时,oracle首先自动在所要操作的表上申请TM类型的锁。当TM锁获得后,再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位(lb 即lock bytes)进行置位。在记录被某一会话锁定后,其它需要访问被锁定对象的会话会按先进先出的方式等待锁的释放,对于select操作而言,并不需要任何锁,所以即使记录被锁定,select语句依然可以执行,实际上,在此情况下,oracle是用到undo的内容进行一致性读来实现的。
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。DML语句能够自动地获得所需的表级锁(table-level lock)与行级锁(row-level lock)。
DML锁,也称为数据锁,确保由多个用户并发访问的数据的完整性。例如,DML锁可防止两个客户从一个在线书店购买某一本书所剩的最后一个拷贝。DML锁也可以防止多个相互冲突的DML或DDL操作产生破坏性干扰。
DML语句自动获取下列类型的锁:
n 行锁(TX)
n 表锁(TM)
 
2.5.1.1  行锁(Row Locks,TX)


行级锁(row-level lock)的作用是防止两个事务同时修改相同的数据行。当一个事务需要修改一行数据时,就需对此行数据加锁。Oracle 对语句或事务所能获得的行级锁的数量没有限制,Oracle 也不会讲行级锁的粒度升级(lock escalation)。行级锁是粒度最精细的锁,因此行级锁能够提供最好的数据并发访问能力及数据处理能力。
Oracle 同时支持多版本并发访问控制(multiversion concurrency control)及行级锁技术(row-level locking),因此用户只有在访问相同数据行时才会出现竞争,具体来说: 
l 读取操作无需等待对相同数据行的写入操作。
l 写入操作无需等待对相同数据行的读取操作,除非读取操作使用了 SELECT ... FOR UPDATE 语句,此读取语句需要对数据加锁。 
l 写入操作只需等待并发地且针对相同数据行的其它写入操作。
提示:读取操作可能会等待对相同数据块(data block)的写入操作,这种情况只会在出现挂起的分布式事务(pending distributed transaction)时偶尔出现。
在执行下列语句时,事务需要获得被修改的每一数据行的排它行级锁(exclusive row lock):INSERT,UPDATE,DELETE,及使用了FOR UPDATE 子句的 SELECT 语句。
在事务被提交或回滚前,此事务拥有在其内部被修改的所有数据行的排它锁,其它事务不能对这些数据行进行修改操作。但是,如果事务由于实例故障而终止,在整个事务被恢复前,数据块级的恢复将使数据块内数据行上的锁释放。执行前面提到的 4 种 SQL 语句时,Oracle 能自动地对行级锁进行管理。
当事务获得了某些数据行上的行级锁时,此事务同时获得了数据行所属表上的表级锁(table lock)。表级锁能够防止系统中并发地执行有冲突的 DDL 操作,避免当前事务中的数据操作被并发地 DDL 操作影响。
 
行级锁机制:
当一个事务开始时,必须申请一个TX锁,这种锁保护的资源是回滚段、回滚数据块。因此申请也就意味着:用户进程必须先申请到回滚段资源后才开始一个事务,才能执行DML操作。申请到回滚段后,用户事务就可以修改数据了。具体顺序如下:
1、首先获得TM锁,保护事务执行时,其他用户不能修改表结构
2、事务修改某个数据块中记录时,该数据块头部的ITL表中申请一个空闲表项,在其中记录事务项号,实际就是记录这个事务要使用的回滚段的地址(应该叫包含)
3、事务修改数据块中的某条记录时,会设置记录头部的ITL索引指向上一步申请到的表项。然后修改记录。修改前先在回滚段将记录之前的状态做一个拷贝,然后修改表中数据。
4、其他用户并发修改这条记录时,会根据记录头部ITL索引读取ITL表项内容,确认是否事务提交。
5、若没有提交,必须等待TX锁释放
从上面的机制来看,无论一个事务修改多少条记录,都只需要一个TX锁。所谓的“行级锁”其实也就是数据块头、数据记录头的一些字段,不会消耗额外的资源。 从另一方面也证明了,当用户被阻塞时,不是被某条记录阻塞,而是被TX锁堵塞。也正因为这点,很多人也倾向把TX锁称为事务锁。这里可通过实验来验证所说 结论。
会话1:




SQL> select * from test;
        ID NAME
---------- --------
         1 A
         2 B
         3 C
 
SQL> savepoint a;
Savepoint created.
 
SQL> update test set name=‘ssss‘ where id=2;
1 row updated. 
 




 
 
会话2,更新同一行发生阻塞:




SQL> update test set name=‘ssdsdsds‘where id=2;
 
 
 
 




 
 
会话1:




SQL> rollback to a;
Rollback complete.
 




 
可以看到,虽然会话1已经撤销了对记录的修改,但是会话2仍然处于等待状态这是因为会话2是被会话1的TX锁阻塞的,而不是被会话1上的行级锁 阻塞(rollback to savepoint不会结束事务) 。




会话3:
SQL> select username,event,sid,blocking_session from v$session where SID IN (146,159);
USERNAME EVENT                                      SID BLOCKING_SESSION
-------- ----------------------------------- ---------- ----------------
HR       enq: TX - row lock contention              146              159
HR       SQL*Net message from client                159 
会话1:
SQL> rollback; 
会话2:
SQL> update test set name=‘ssdsdsds‘where id=2;
 1 row updated. 
会话3:
SQL> select username,event,sid,blocking_session from v$session where username=‘HR‘;
USERNAME EVENT                                      SID BLOCKING_SESSION
-------- ----------------------------------- ---------- ----------------
HR       SQL*Net message from client                159 




 
事务结束,tx锁释放,会话2update执行成功。 
 
行锁,也称为TX 锁,是一个表中单个行上的锁。一个事务在被INSERT、UPDATE、DELETE、MERGE、或SELECT ... FOR UPDATE 等语句所修改的每一行上获取一个行锁。行锁一直存在直到事务提交或回滚。行锁主要作为一种排队的机制,以防止两个事务修改相同的行。数据库始终以独占模式锁定修改的行,以便其它事务不能修改该行,直到持有锁的事务提交或回滚。行锁定提供了近乎最细粒度的锁定,并因此提供了近乎最佳的并发性和吞吐量。
如果一个事务因为数据库实例失效而终止,会先进行块级恢复以使行可用,之后进行整个事务恢复。
2.5.1.2  表锁(Table Locks,TM)
表级锁(table-level lock)的作用是对并发的 DDL 操作进行访问控制,例如防止在 DML 语句执行期间相关的表被移除。当用户对表执行 DDL 或 DML 操作时,将获取一个此表的表级锁。表级锁不会影响其他并发的 DML 操作。对于分区表来说,表级锁既可以针对整个表,也可以只针对某个分区。
当用户执行以下 DML 语句对表进行修改:INSERT,UPDATE,DELETE,及 SELECT ... FOR UPDATE,或执行 LOCK TABLE 语句时,事务将获取一个表级锁。这些 DML 语句获取表级锁的目的有两个:首先保证自身对表的访问不受其它事务 DML 语句的干扰,其次阻止其它事务中和自身有冲突的 DDL 操作执行。任何类型的表级锁都将阻止对此表的排它 DDL 锁(exclusive DDL lock),从而阻止了必须具备排它 DDL 锁才能执行的 DDL 操作。例如,当一个未提交的事务拥有某个表上的锁时,此表就无法被修改定义或被移除。
表级锁具有以下几种模式:行共享(row share,RS),行排它(row exclusive,RX),共享(share,S),共享行排它(share row exclusive,SRX),及排它(exclusive,X)。各种模式的表级锁具有的限制级别决定了其是否能与其他表级锁共处于同一数据表上。
下表显示了各种语句所获得的表级锁的模式,以及此模式下被允许或禁止的操作。
ORACLE里锁有以下几种模式:
 
锁的兼容模式如下表所示:
 
表锁,也称为TM锁,当一个表被INSERT、UPDATE、DELETE、MERGE、带FOR UPDATE子句的SELECT等修改时,由相关事务获取该锁。DML操作需要表锁来为事务保护DML对表的访问,并防止可能与事务冲突的DDL操作。
表锁可能以下列模式之一持有:
 
一、 行共享(RS)  Row Share (RS)
这种锁也被称为子共享表锁(SS,subshare table lock),表示在表上持有锁的事务在表中有被锁定的行,并打算更新它们。行共享锁是限制最少的表级锁模式,提供在表上最高程度的并发性。
1、 实验
ROW SHARE模式允许同时访问被锁定的表,但是禁止用户以排它方式锁定整个表。ROW SHARE与SHARE UPDATE相同,只是为了兼容早期的Oracle版本。对应lmode2,row-S (SS)。
版本:11.2.0.4




会话1:
SYS@lhrdb> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@lhrdb S1> select userenv(‘sid‘) from dual;
 
USERENV(‘SID‘)
--------------
            6
 
SYS@lhrdb S1> LOCK TABLE SCOTT.EMP IN ROW SHARE MODE;
 
Table(s) Locked.
会话2:
SYS@lhrdb> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@lhrdb S2> select userenv(‘sid‘) from dual;
 
USERENV(‘SID‘)
--------------
            114
 
SYS@lhrdb S2> LOCK TABLE SCOTT.EMP IN EXCLUSIVE MODE;
 
 
 
====>>>>> 产生了阻塞
查询2个会话的锁:
SYS@lhrdb S1> SELECT D.SID, D.TYPE, D.ID1, D.ID2, D.LMODE, D.REQUEST, D.CTIME, D.BLOCK
  2    FROM V$LOCK D
  3   WHERE D.SID IN (114, 6)
  4   ORDER BY D.SID, D.TYPE;
       SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- -- ---------- ---------- ---------- ---------- ---------- ----------
         6 AE        100          0          4          0        231          0
         6 TM      86893          0          2          0        169          1
       114 AE        100          0          4          0        378          0
       114 TM      86893          0          0          6        144          0
       114 TO      79619          1          3          0        376          0




 
 
SELECT D.SID, D.TYPE, D.ID1, D.ID2, D.LMODE, D.REQUEST, D.CTIME, D.BLOCK
  FROM V$LOCK D
 WHERE D.SID IN (114, 6)
 ORDER BY D.SID, D.TYPE;
 
由BLOCK列可以看到sid为6的会话阻塞了一个会话,这里其实就是114,而114正在请求模式为6的锁。将2个会话提交后继续测试:




SYS@lhrdb S1> LOCK TABLE SCOTT.EMP IN SHARE UPDATE MODE;
 
Table(s) Locked.
 
SYS@lhrdb S1> SELECT D.SID, D.TYPE, D.ID1, D.ID2, D.LMODE, D.REQUEST, D.CTIME, D.BLOCK
  2    FROM V$LOCK D
  3   WHERE D.SID IN (114, 6)
  4     AND D.TYPE = ‘TM‘
  5   ORDER BY D.SID, D.TYPE;
 
       SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- -- ---------- ---------- ---------- ---------- ---------- ----------
         6 TM      86893          0          2          0        387          0
 




 
 
二、 行独占表锁  Row Exclusive Table Lock (RX)
这种锁也被称为子独占表锁(SX,subexclusive table lock),通常表示持有锁的事务已更新了表行或发出了SELECT...FOR UPDATE。一个SX锁允许其它事务并发地查询、插入、更新、删除、或锁定在同一个表中的其它行。因此,SX锁允许多个事务对同一个表同时获得SX和子共享表锁。
ROW EXCLUSIE类似于ROW SHARE模式,但是不能应用在SHARE模式中。当update,insert,delete发生时,ROW EXCLUSIVE会自动获得。对应lmode3,row-X (SX) 。
1、 实验
实验内容:but it also prohibits locking in SHARE mode




会话1:
SQL> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@oratest S1>  select distinct sid from v$mystat;
 
       SID
----------
        21
SYS@oratest S1> lock table scott.emp in share mode;
 
Table(s) Locked.
 
 
会话2:
SQL> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@oratest S2>  select distinct sid from v$mystat;
 
       SID
----------
       142
 
SYS@oratest S2>  lock table scott.emp in  row exclusive mode;
 
 
 
====>>>>> 产生了阻塞
 
 
查看锁:
SYS@oratest S1> set line 9999
SYS@oratest S1> select * from v$lock where sid in (21,142);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000774D8518 00000000774D8570        142 TO      68064          1          3          0       7021          0
00000000774D9870 00000000774D98C8        142 TO      76985          1          3          0       7365          0
00000000774D9DC8 00000000774D9E20         21 AE        100          0          4          0        162          0
00000000774DA068 00000000774DA0C0        142 AE        100          0          4          0       7379          0
00007F567ADC2700 00007F567ADC2760        142 TM      75335          0          0          3         36          0
00007F567ADC2700 00007F567ADC2760         21 TM      75335          0          4          0         58          1
 
6 rows selected.
 
SYS@oratest S1> select * from v$lock where sid in (21,142) AND TYPE IN (‘TX‘,‘TM‘);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F567ADC7818 00007F567ADC7878        142 TM      75335          0          0          3         76          0
00007F567ADC7818 00007F567ADC7878         21 TM      75335          0          4          0         98          1
 
SYS@oratest S1> SELECT * FROM DBA_DML_LOCKS;
 
SESSION_ID OWNER                          NAME                           MODE_HELD     MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS
---------- ------------------------------ ------------------------------ ------------- ------------- ------------ ----------------------------------------
       142 SCOTT                          EMP                            None          Row-X (SX)             101 Not Blocking
        21 SCOTT                          EMP                            Share         None                   123 Blocking
 
SYS@oratest S1> 
 




 
这里可以看到会话1的TM4阻塞了会话2的TM3。
提交2个会话后,接着实验:ROW EXCLUSIVE locks are automatically obtained when updating, inserting, or deleting. 




SYS@oratest S1>  update scott.emp set sal=sal where empno=7369;
 
1 row updated.
 
SYS@oratest S1> select * from v$lock where sid in (21,142) AND TYPE IN (‘TX‘,‘TM‘);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F567ADE6AC8 00007F567ADE6B28         21 TM      75335          0          3          0          4          0
0000000076227AB0 0000000076227B28         21 TX     196620       1097          6          0          4          0
 




 
当会话1做了修改而没有commit或者rollback时,这里有两个锁,其中一个就是TM3的,一个是TX6的。
 
三、 共享表锁  Share Table Lock (S)
由某个事务拥有的共享表锁允许其它事务查询(而不使用SELECT...FOR UPDATE),但是更新操作只能在仅有单个事务持有共享表锁时才允许。因为可能有多个事务同时持有共享表锁,所以持有此锁不足以确保一个事务可以修改该表。
SHARE允许同时查询,但是禁止更新被锁定的表。对应lmode4,share (S) 。
1、 实验




会话1:
SQL> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@oratest S1>  select distinct sid from v$mystat;
 
       SID
----------
        21
SYS@oratest S1> lock table scott.emp in share mode;
 
Table(s) Locked.
 
 
会话2:
SQL> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@oratest S2>  select distinct sid from v$mystat;
 
       SID
----------
       142
 
SYS@oratest S2>  update scott.emp set sal=sal where empno=7369;
 
 
 
====>>>>> 产生了阻塞
 
 
查看锁:
SYS@oratest S1> select * from v$lock where sid in (21,142) AND TYPE IN (‘TX‘,‘TM‘);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F567ADE6AC8 00007F567ADE6B28        142 TM      75335          0          0          3         43          0
00007F567ADE6AC8 00007F567ADE6B28         21 TM      75335          0          4          0         62          1
 
 
SYS@oratest S1> SELECT * FROM DBA_DML_LOCKS;
 
SESSION_ID OWNER    NAME   MODE_HELD     MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS
---------- -------- ------ ------------- ------------- ------------ ---------------
       142 SCOTT    EMP    None          Row-X (SX)             113 Not Blocking
        21 SCOTT    EMP    Share         None                   132 Blocking
SYS@oratest S1> 
 




 
这里可以看到会话1的TM4阻塞了会话2的TM3。
 
四、 共享行独占表锁  Share Row Exclusive Table Lock (SRX)
这种锁也称为共享子独占表锁(SSX,share-subexclusive table lock),比共享表锁的限制性更强。一次只能有一个事务可以获取给定的表上的SSX锁。由某个事务拥有的SSX锁允许其它事务查询该表(除SELECT...FOR UPDATE)但不能更新该表。
共享行级排它锁有时也称共享子排它锁(Share Subexclusive Table Lock,SSX),它比共享锁有更多限制。定义共享行级排它锁的语法为:
Lock Table TableName In Share Row Exclusive Mode;
1、 实验




会话1:
SQL> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@oratest S1>  select distinct sid from v$mystat;
 
       SID
----------
        21
SYS@oratest S1> lock table scott.emp  in  share row exclusive  mode;
 
Table(s) Locked.
 
 
会话2:
SQL> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@oratest S2>  select distinct sid from v$mystat;
 
       SID
----------
       142
 
SYS@oratest S2>  lock table scott.emp  in  share mode;
 
 
 
====>>>>> 产生了阻塞
 
 
查看锁:
SYS@oratest S1> select * from v$lock where sid in (21,142) AND TYPE IN (‘TX‘,‘TM‘);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00007F567ADE7B00 00007F567ADE7B60        142 TM      75335          0          0          4         21          0
00007F567ADE7B00 00007F567ADE7B60         21 TM      75335          0          5          0         69          1
SYS@oratest S1> SELECT * FROM DBA_DML_LOCKS;
 
SESSION_ID OWNER   NAME   MODE_HELD     MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS
---------- ------- ------ ------------- ------------- ------------ ---------------
       142 SCOTT   EMP    None          Share                   44 Not Blocking
        21 SCOTT   EMP    S/Row-X (SSX) None                    92 Blocking




 
这里可以看到会话1的TM5阻塞了会话2的TM4。
 
五、 独占表锁 Exclusive Table Lock (X)
这种锁是最严格的锁,禁止其它事务执行任何类型的DML语句,或在表上放置任何类型的锁。
EXCLUSIVE  EXCLUSIVE permits queries on the locked table but prohibits any other activity on it.
EXCLUSIVE模式允许查询被锁表上的数据,但是禁止任何其他任何活动(这里我理解是禁止添加其他任何模式的锁)。对应lomde6,exclusive (X) 。
1、 实验




会话1:
SQL> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@oratest S1>  select distinct sid from v$mystat;
 
       SID
----------
        21
SYS@oratest S1> CREATE TABLE SCOTT.EMP_01 AS SELECT * FROM SCOTT.EMP;
 
Table created.
 
SYS@oratest S1>  update scott.emp_01 set sal=sal where empno=7369;
 
1 row updated.
 
会话2:
SQL> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@oratest S2>  select distinct sid from v$mystat;
 
       SID
----------
       142
 
SYS@oratest S2>  DELETE FROM scott.emp_01  where empno=7369;
 
 
 
====>>>>> 产生了阻塞
 
 
查看锁:
SYS@oratest S1> select * from v$lock where sid in (21,142) AND TYPE IN (‘TX‘,‘TM‘);
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000000774D9EA8 00000000774D9F00        142 TX     393247       1337          0          6         28          0
00007F567ABBC0A0 00007F567ABBC100        142 TM      77624          0          3          0         28          0
00007F567ABBC0A0 00007F567ABBC100         21 TM      77624          0          3          0         36          0
0000000076255548 00000000762555C0         21 TX     393247       1337          6          0         36          1
 
SYS@oratest S1> SELECT * FROM DBA_DML_LOCKS;
 
SESSION_ID OWNER    NAME     MODE_HELD     MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS
---------- -------- -------- ------------- ------------- ------------ ---------------
       142 SCOTT    EMP_01   Row-X (SX)    None                    35 Not Blocking
        21 SCOTT    EMP_01   Row-X (SX)    None                    43 Not Blocking




 
在这里,从BLOCK字段可以看到会话1的TM3并没堵塞会话2的TM3,这里真正发生堵塞的是会话1的TX6。
这里还有一个锁定对象的问题。上面两个TM3的锁针对的对象是object_id为77624的表,既然描述是类似行共享,自然是不会堵塞的。而两个TX6的锁针对的对象可以理解成表中的行,在这些行上添加EXCLUSIVE锁(lmode6,exclusive (X) )自然是会堵塞其他的EXCLUSIVE锁的。
解决这种类型的锁堵塞当然就是在代码中尽早commit结束事务。很多地方都写到尽早commit可以提高运行效率,这里所指的是释放锁(特别是lmode6的EXCLUSIVE锁)减少堵塞,以提高并发性。(不是以减少数据的量来提高效率的,事实上不管多大的数据量,一个commit的过程都是很"平"的。
 
 
2、 INSERT /*+APPEND*/ INTO加6级TM和TX独占锁




会话1:
SYS@lhrdb> set sqlprompt "_user‘@‘_connect_identifier S1> "
SYS@lhrdb S1> SELECT DISTINCT SID FROM  V$MYSTAT;
 
       SID
----------
        27
SYS@lhrdb S1> CREATE TABLE T_APPEND_161107_LHR AS SELECT * FROM DUAL;
 
Table created.
 
SYS@lhrdb S1> INSERT /*+ APPEND */ INTO T_APPEND_161107_LHR SELECT * FROM DUAL;
 
3 rows created.
 
会话2:
SYS@lhrdb> set sqlprompt "_user‘@‘_connect_identifier S2> "
SYS@lhrdb S2>  SELECT DISTINCT SID FROM  V$MYSTAT;
 
       SID
----------
       162
 
SYS@lhrdb S2> INSERT /*+ APPEND */ INTO T_APPEND_161107_LHR SELECT * FROM DUAL;
 
 
  <<<<<<<<<-------- 产生了阻塞
 




 
 
会话3:




SYS@lhrdb> set sqlprompt "_user‘@‘_connect_identifier S3> "
SYS@lhrdb S3> set line 9999
SYS@lhrdb S3> SELECT * FROM V$LOCK T WHERE T.SID IN (27,162) AND T.TYPE IN (‘TX‘,‘TM‘) ORDER BY T.SID ;
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000001109F5A40 00000001109F5AA0         27 TM     100957          0          6          0       2217          1
070001007C7EB2B0 070001007C7EB328         27 TX     589843      58249          6          0       2217          0
00000001109F5A40 00000001109F5AA0        162 TM     100957          0          0          6       2214          0
 
====>>>>> 过了很久
SYS@lhrdb S3> SELECT * FROM V$LOCK T WHERE T.SID IN (27,162) AND T.TYPE IN (‘TX‘,‘TM‘) ORDER BY T.SID ;
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000001109F6A78 00000001109F6AD8         27 TM     100957          0          6          0       2882          1
070001007C7EB2B0 070001007C7EB328         27 TX     589843      58249          6          0       2882          0
00000001109F6A78 00000001109F6AD8        162 TM     100957          0          0          6       2879          0
 
SYS@lhrdb S3> /
 
ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
00000001109F5A40 00000001109F5AA0         27 TM     100957          0          6          0       2885          1
070001007C7EB2B0 070001007C7EB328         27 TX     589843      58249          6          0       2885          0
00000001109F5A40 00000001109F5AA0        162 TM     100957          0          0          6       2882          0
 
 




 
 
其中,会话1的sid为27,分别在TX和TM级别,拥有LMODE为6的X锁。BLOCK为1说明会话1阻塞了其它会话(0表示没有阻塞,2表示RAC环境需要用GV$LOCK)。CTIME表示拥有此锁的时间,单位为秒。会话2的sid为162,REQUEST为6表示正在请求模式为6的锁。
当TYPE列为TM的时候,即对于TM锁来说,ID1列表示被锁定的对象的对象ID,ID2始终为0,如下:




SYS@lhrdb S3> COL OWNER FORMAT A5
SYS@lhrdb S3> COL OBJECT_NAME FORMAT A20
SYS@lhrdb S3> SELECT D.OWNER,D.OBJECT_NAME,D.OBJECT_ID FROM DBA_OBJECTS D WHERE D.OBJECT_ID = 100957;
OWNER OBJECT_NAME           OBJECT_ID
----- -------------------- ----------
SYS   T_APPEND_161107_LHR      100957
 




 
当TYPE列为TX的时候,即对于TX锁来说,ID1列表示事务使用的回滚段编号以及在事务表中对应的记录编号,ID2表示该记录编号被重用的次数(wrap),ID1列表示事务的信息,如下:




SYS@lhrdb S3> SELECT A.TADDR FROM V$SESSION A WHERE SID = 27;
 
TADDR
----------------
070001007C7EB2B0
 
SYS@lhrdb S3> SELECT A.XIDUSN, A.XIDSLOT, A.XIDSQN
  2    FROM V$TRANSACTION A
  3   WHERE A.ADDR = ‘070001007C7EB2B0‘;
 
    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         9         19      58249
 
SYS@lhrdb S3> SELECT TRUNC(589843 / POWER(2, 16)) AS UNDO_SEG#,
  2         BITAND(589843, TO_NUMBER(‘ffff‘, ‘xxxx‘)) + 0 AS SLOT#,
  3                      58249 XIDSQN
  4    FROM DUAL; 
 
 UNDO_SEG#      SLOT#     XIDSQN
---------- ---------- ----------
         9         19      58249
 
SYS@lhrdb S3> SELECT SID,
  2         STATUS,
  3         SQL_ID,
  4         LAST_CALL_ET,
  5         BLOCKING_INSTANCE,
  6         BLOCKING_SESSION,
  7         EVENT
  8    FROM GV$SESSION
  9   WHERE BLOCKING_SESSION IS NOT NULL;
 
       SID STATUS   SQL_ID        LAST_CALL_ET BLOCKING_INSTANCE BLOCKING_SESSION EVENT
---------- -------- ------------- ------------ ----------------- ---------------- ---------------------
       162 ACTIVE   2kvrfkkjukryr         4875                 1               27 enq: TM - contention
 
SYS@lhrdb S3> select sql_text from v$sql where sql_id=‘2kvrfkkjukryr‘;
 
SQL_TEXT
----------------------------------------------------
INSERT /*+ APPEND */ INTO T_APPEND_161107_LHR SELECT * FROM DUAL
 
SYS@lhrdb S3> SELECT * FROM DBA_DML_LOCKS D WHERE D.SESSION_ID IN (27, 162);
 
SESSION_ID OWNER NAME                  MODE_HELD     MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS
---------- ----- --------------------- ------------- ------------- ------------ ---------------
        27 SYS   T_APPEND_161107_LHR   Exclusive     None                   647 Blocking
       162 SYS   T_APPEND_161107_LHR   None          Exclusive              468 Not Blocking




 
 
从视图DBA_DML_LOCKS可以非常直观的看出锁的情况,会话1即SID为27,拥有Exclusive的排它锁,没有请求其它锁,而会话2即SID为162正在请求Exclusive的排它锁。
SELECT * FROM V$EVENT_NAME WHERE NAME = ‘enq: TM - contention‘;
 
从会话查询锁的信息:
SELECT SID,
       STATUS,
       SQL_ID,
       LAST_CALL_ET,
       EVENT,
       A.P1,
       A.P2,
       A.P3,
       CHR(BITAND(P1, -16777216) / 16777215) ||
       CHR(BITAND(P1, 16711680) / 65535) "LOCK",
       BITAND(P1, 65535) "MODE",
       (SELECT OBJECT_NAME FROM DBA_OBJECTS D WHERE D.OBJECT_ID = A.P2) OBJECT_NAME
  FROM GV$SESSION A
 WHERE A.EVENT = ‘enq: TM - contention‘;
 
会话1提交,查看会话2的情况:




SYS@lhrdb S1> commit;
 
Commit complete.
 
SYS@lhrdb S1> 
会话2:
SYS@lhrdb S2> INSERT /*+ APPEND */ INTO T_APPEND_161107_LHR SELECT * FROM DUAL;
 
 
 
3 rows created.
 
SYS@lhrdb S2> SYS@lhrdb S2> SYS@lhrdb S2> commit;
 
Commit complete.
 
SYS@lhrdb S2> SELECT * FROM V$LOCK T WHERE T.SID IN (27,162) AND T.TYPE IN (‘TX‘,‘TM‘) ORDER BY T.SID ;
 
no rows selected
 




 
 
二.5.1.3  总结
执行不同的 DML 语句时,Oracle自动地对数据加锁。
一、 查询操作默认获取的锁
执行查询(query)的 SQL 语句不易与其他 SQL 语句冲突,因为查询只需读取数据。除了 SELECT 之外,INSERT,UPDATE,及 DELETE 语句中也可能包含隐式的查询。因此,以下语句都属于查询操作:
SELECT 
INSERT ... SELECT ... ; 
UPDATE ... ; 
DELETE ... ; 
但是以下语句不属于查询操作:
SELECT ... FOR UPDATE OF ... ;
查询操作具备以下特性:
l 查询无需获取数据锁。因此当某事务查询数据表时,其它事务可以并发地查询、更新同一个表,包括此表中正在被查询的数据行。没有使用 FOR UPDATE 子句的 SELECT 语句无需获取任何数据锁,因此也不会阻塞任何操作,此类查询在 Oracle 中被称为非阻塞查询(nonblocking query)。 
l 执行查询也不受数据锁的限制。(在某些特殊情况下,查询需要等待挂起的分布式事务所拥有的数据锁) 
二、 INSERT,UPDATE,DELETE,及 SELECT ... FOR UPDATE 语句默认获取的锁
INSERT,UPDATE,DELETE,及 SELECT ... FOR UPDATE 语句默认获取的锁有以下特点: 
l 包含 DML 语句的事务需要获得被其修改的数据行上的排它行级锁(exclusive row lock)。在拥有锁的事务提交或回滚前,其它事务不能更新或删除被加锁的数据行。 
l 事务无需获取 DML 语句内的子查询(subquery)或隐式查询(implicit query)(例如 WHERE 子句内的查询)所选择的行上的行级锁。DML 内的子查询或隐式查询获得的数据相对查询开始的时间点满足一致性,这些查询不会看到 DML 语句自身对数据的影响。 
l 事务内的查询能够看到本事务内之前执行的 DML 语句对数据的修改,但无法看到本事务开始后执行的其它事务对数据的修改。 
l 事务内的 DML 语句除了需要获得必要的排它行级锁(exclusive row lock)外,至少还需获得包含被修改数据行的表上的行排它表级锁(row exclusive table lock)。如果事务已经获得了相关表上的共享表级锁(share),共享行排它表级锁(share row exclusive),或排它表级锁(exclusive),那么就无需获取行排它表级锁了。如果事务已经获得了相关表上的行共享表级锁(row share table lock),Oracle 将自动地将此锁转换为行排它表级锁。 
 
2.5.2  DDL锁(DDL Locks)
当某个运行中的DDL操作正在操作或引用某模式对象时,数据字典(DDL)锁保护该模式对象的定义。在DDL操作的过程中,只有被修改或引用的单个模式的对象被锁定。数据库绝不会锁定整个数据字典。
Oracle数据库将为任何要求锁的DDL事务自动获取DDL锁。用户不能显式请求DDL锁。例如,如果用户创建一个存储过程,则数据库自动为过程定义中引用的所有模式对象获取DDL锁。DDL锁防止在过程编译完成之前,这些对象被更改或删除。
数据字典锁(data dictionary lock,DDL)的作用是在执行 DDL 操作时对被修改的方案对象或其引用对象的定义进行保护。管理员及开发者应该意识到 DDL 语句将会隐式地提交一个事务。例如,用户创建一个存储过程时,相当于执行一个只包含一条 SQL 语句的事务,Oracle 会自动获取过程定义中所引用的所有方案对象的 DDL 锁。DDL 锁能够防止编译期间过程所引用的对象被其它事务修改或移除。
当 DDL 事务需要时 Oracle 将自动地为其获取数据字典锁。用户不能显示地获取 DDL 锁。只有在 DDL 操作中被修改或引用的对象才会被加锁,整个数据字典不会被加锁。
当用户发布DDL(Data Definition Language)语句时会对涉及的对象加DDL锁。由于DDL语句会更改数据字典,所以该锁也被称为字典锁。
DDL锁能防止在用DML语句操作数据库表时,对表进行删除,或对表的结构进行更改。
对于DDL锁,要注意的是:
l DDL锁只锁定DDL操作所涉及的对象,而不会锁定数据字典中的所有对象。
l DDL锁由Oracle自动加锁和释放。不能显式地给对象加DDL锁,即没有加DDL锁的语句。
l 在过程中引用的对象,在过程编译结束之前不能被改变或删除,即不能被加排它DDL锁。
DDL 锁可以分为三类:排它 Ddl 锁(Exclusive DDL Lock),共享 Ddl 锁(Share DDL Lock),及可中断的解析锁(Breakable Parse Lock)。
2.5.2.1    

本文由职坐标整理并发布,希望对同学们学习Oracle有所帮助,更多内容请关注职坐标数据库Oracle数据库频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程