LLL的数据库培训—第二部分—Oracle培训—第21讲—oracle的锁管理(待整理)
一、自行整理
各种锁的使用:
一、什么是锁,锁的概念
1、锁是做什么的。
数据库是一个多用户使用的共享资源。
当多个用户并发的存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。
若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。
锁(lock)机制用于管理对共享资源的并发访问。
注意,这里说的是“共享资源”而不是“数据库行”。Oracle会在行级对表数据锁定,不过oracle也会在其他多个级别上使用锁,从而对多种不同的资源提供并发访问。
例如,执行一个存储过程时,过程本身会以某种模式锁定,以允许其他用户执行这个过程,但是不允许另外的用户以任何方式修改这个过程。
数据库中使用锁是为了支持对共享资源进行并发访问,与此同时还能提供数据完整性和一致性。
需要了解的是有多少种数据库,其中就可能有多少种实现锁定的方法。你可能对某个特定的关系型数据库管理系统(RDBMS)的锁定模型有一定的经验,但是每个数据库中对实现锁定的方式都大相径庭。
在oracle中,你会了解到下面几点:
1.事务是每个数据库的核心,他们是好东西。
2.应该延迟到适当的时刻才提交。不要太快提交,以避免对系统带来压力。这是因为,如果事务很长或很大,一般不会对系统有压力。相应的原则是:在必要时才提交,事务的大小只应该根据业务逻辑来定。
3.只要需要,就应该尽可能长时间地保持对数据所加的锁。这些锁是你能利用的工具,而不是然给你退避三舍的东西。锁不是稀有资源(而在比如sqlserver中,这样做是疯狂的,会极大的降低性能)。
4.在oracle中,行级锁没有相关的开销,根本没有。不论你是有1个行级锁,还是1000000个行级锁,专用于锁定这个信息的资源数是一样的。当然,与修改1行数据相比,修改1000000行要做的工作肯定多得多,但是对1000000行锁定所需的资源数与对1行锁定所需的资源完全相同,这是一个固定的常量。
5.不要以为锁升级“对系统更好”(例如,使用表锁而不是行锁)。在oracle中,锁升级对系统没有任何好处,不会节省任何资源。
6.可以同时得到并发性和一致性。每次你都能快速而准确地得到数据。数据读取器不会被数据写入器阻塞。数据写入器也不会被数据读取器阻塞。这是oracle与大多数其他关系数据库之间的根本区别之一。
未完成---见文章后面部分。
2、什么情况加锁,如何加锁。
当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。
加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
加锁后可防止多个会话同时更改同一数据;
是在指定语句的最低可能级别自动获取的不会升级???
3、锁的分类
根据保护对象的不同,Oracle数据库锁可分为:
DML lock(data locks,数据锁):用于保护数据的完整性。
DDL lock(dictionary locks,字典锁):用于保护数据库对象的结构(例如表、视图、索引的结构定义)。
SYSTEM locks(系统锁)
Internal locks 和latches(内部锁与闩):保护内部数据库结构。
Distributed locks(分布式锁):用于OPS(并行服务器)中。
PCM locks(并行高速缓存管理锁):用于OPS(并行服务器)中。
4、如何释放dml锁
(1)退出sqlplus
(2)commit提交
(3)rollback回滚
二、Oracle的表DML锁的五种加锁模式简介:
行级共享锁(RS锁),又共享更新锁(share update)
行级排他锁(RX锁)
共享锁方式(S锁)—表级锁
共享行级排他锁(SRX锁)
独占锁方式(x锁)—排它锁
以下是五种锁模式的强弱其别:
EXCLUSIVE > ROW SHARE EXCLUSIVE > SHARE > ROW EXCLUSIVE > ROW SHARE
1、row share(RS锁):
--允许对锁定的表进行并发访问,但禁止在会话中锁定整个表进行独占访问(不允许其他事务对相同的表增加排他锁)。
2、row exclusive(RX锁):
--与row share 相同,但是同时禁止以share 模式锁定。
--更新、插入或删除数据时会自动获取row exclusive 锁。
--row exclusive 锁允许多个进程执行读取,但只允许一个进程执行写入。
3、share(S锁):
--数据并发处理(不允许其他事务对相同的表增加排他锁)。
4、share row exclusive(RSX锁):
--用于查询整个表,允许其他人查询表中的行,但禁止其他人在share 模式下锁定表或更新行。
5、exclusive(X锁):
--允许查询锁定表,禁止对锁定表执行任何其它活动,需要有exclusive 锁才能删除表。
三、Oracle的表DML锁有如下五种加锁方式详解及案例测试
1、行级共享锁(RS锁),又共享更新锁( share update)
SQ>lock table test in share update mode;
--通常是通过select … from for update语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。
--当表上添加了RS锁定以后,--允许其他事务同时给此表加RS锁,不允许其他事务对相同的表添加排他锁(X锁)
--但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。
①session1使用RS锁,并更新一行
14:48:08 TEST@mesorcl>lock table test in share update mode;
Table(s) Locked.
14:48:09 TEST@mesorcl>update test set name='TTT' where id=5;
②seesion2 同时更新此行,被挂起
14:49:41 TEST@mesorcl>update test set name='TTT2' where id=5;
①session1使用RS锁
14:55:52 TEST@mesorcl>lock table test in share update mode;
②session2对test表添加RS锁
14:56:50 TEST@mesorcl>lock table test in share update mode;
③session2对test表添加X锁,被挂起
14:57:43 TEST@mesorcl>lock table test in exclusive mode;
①session1使用RS锁
14:59:52 TEST@mesorcl>lock table test in share update mode;
②session2对test表更新其他行,不进行commit
15:03:20 TEST@mesorcl>update test set name='TTT2' where id=1;
1 row updated.
Elapsed: 00:00:00.01
③session1无法对上述行进行操作(被挂起)
15:04:05 TEST@mesorcl>update test set name='TTT2' where id=1;
2、行级排他锁(RX锁)
SQL>lock table test in row exclusive mode;
--当进行DML操作时会自动在被更新的表上添加RX锁,
--也可以通过执行lock命令显式的在表上添加RX锁。--lock table test in row exclusive mode;
--在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,
--但是不允许其他事务对相同的表添加排他锁(X锁)。
(1)方案1:session1 增加RX锁,对id=1的行进行更新,session2可以修改其他行
①session1使用RX锁,更新id=1的行
15:21:50 TEST@mesorcl>lock table test in row exclusive mode;
15:22:53 TEST@mesorcl>update test set name='TTT2' where id=1;
②session2对test表可以更新其他行
15:23:53 TEST@mesorcl>update test set name='TTT3' where id=3;
(2)方案2:session1 增加RX锁,session2也增加RX锁
①session1使用RX锁
15:25:16 TEST@mesorcl>lock table test in row exclusive mode;
Table(s) Locked.
②session1使用RX锁
15:25:30 TEST@mesorcl>lock table test in row exclusive mode;
Table(s) Locked.
(3)方案3:session1 增加RX锁,session2增加X锁,被挂起,不被允许
①session1使用RX锁
15:28:56 TEST@mesorcl>lock table test in row exclusive mode;
①session2X锁,被挂起
15:28:53 TEST@mesorcl>lock table test in exclusive mode;
3、共享锁方式(share-S锁)—表级锁
SQL>lock table test in share mode;
--可通过lock table <table_name> in share mode命令添加该S锁。在该锁定模式下,不允许任何用户更新表。
--多个用户可以同时加S锁,双方都无法进行数据的更新:
--但是允许其他用户发出select …from for update命令对表添加RS锁(也就是行级锁),允许并发查询,但禁止更新锁定的表。
--需要有share锁才能创建表的索引,创建时会自动请求该锁。
--但是,创建联机索引的操作在建立索引时需要有rowshare 锁。
--不允许其他事务增加排他锁。
(1)案例1-该锁定模式下,不允许任何其他用户(或说session)更新表,但可以查询:
①在用户test的session1中给表test添加S锁
10:36:45 TEST@mesorcl>lock table test in share mode;
②session1中查询数据,可以正常查询
10:38:29 TEST@mesorcl>select * from test;
ID NAME
---------- ----------
1 LLL
2 XXX
5 TTT
③session2中查询数据,可以正常查询
10:40:29 TEST@mesorcl>select * from test;
ID NAME
---------- ----------
1 LLL
2 XXX
5 TTT
④session2进行更新数据,被挂起
10:58:33 TEST@mesorcl>update test set name='MMM' where id=5;
(2)案例2-该锁定模式下,两个会话(session)同时加S锁,则双方都无法进行数据的更新:
①session1和session2同时进行加S锁
--session1:
11:12:08 TEST@mesorcl>lock table test in share mode;
--session2:
11:13:12 TEST@mesorcl>lock table test in share mode;
②session1和session2都可以进行查询
--session1:
11:16:03 TEST@mesorcl>select * from test;
--session2:
11:16:09 TEST@mesorcl>select * from test;
③session1更新数据被挂起
11:16:01 TEST@mesorcl>update test set name='MMM' where id=1;
④session2更新数据同样被挂起
11:14:36 TEST@mesorcl>update test set name='MMM' where id=5;
(3)案例3—select * from test for update(锁定表)
① session1设置S锁,可以进行查询
11:38:19 TEST@mesorcl>lock table test in share mode;
②session2添加ts锁
11:39:51 TEST@mesorcl>select * from test for update;
ID NAME
---------- ----------
1 MMM
2 XXX
5 TTT
Elapsed: 00:00:00.00
③session1 更改表被挂起
11:39:57 TEST@mesorcl>update test set name='LLL' where id=5;
4、独占锁方式( exclusive-x锁)—排它锁
SQL>lock table test in exclusive mode;
--可通过lock table in exclusive mode命令添加X锁。
--在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询
(1)案例1:session1添加x锁,session2进行查询,dml操作,ddl操作。
①session1上锁
11:54:44 TEST@mesorcl>lock table test in exclusive mode;
②session2执行查询
11:55:44 TEST@mesorcl>select * from test;
ID NAME
---- -----
1 MMM
2 XXX
5 LLL
③session02执行dml被挂起
11:55:55 TEST@mesorcl>update test set name='KKK' where id=5;
④session2执行ddl操作直接报错
11:57:49 TEST@mesorcl>drop table test ;
drop table test
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
(2)案例2—多session添加x锁
①session1上锁
11:54:44 TEST@mesorcl>lock table test in exclusive mode;
Table(s) Locked.
②session2上锁,被挂起,说明同一时间,只能一个会话可以添加x锁。
12:03:22 TEST@mesorcl>lock table test in exclusive mode;
注:共享锁(S锁)和排它锁(X锁)的区别
--share mode的lock 可以被多个session获取,如果多个session 都获取到share lock, 则所有的session都不能对表进行更改操作,只能进行查询,这也许就是SHARE的含义,大家只许看不许摸,谁也没有特权!
--exclusive mode的lock只能被一个session获取,而且其他session也不能对该表加上share 锁来企图阻止获取exclusive 锁的session对表进行更改,这个也是很好理解的嘛,这叫独占式,人家花钱买到的属于自己的东西,你凭啥不让人家碰碰呢!
5、共享行级排他锁(SRX锁)
SQL>lock table test in share row exclusive mode;
--通过lock table <table_name> in share row exclusive mode命令添加SRX锁。
--该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。
(1)方案1:session1增加SRX锁,session进行DML操作,不被允许
①session1 执行srx锁
15:34:18 TEST@mesorcl>lock table test in share row exclusive mode;
②session2 进行DML操作,被挂起,无法执行
15:34:25 TEST@mesorcl>update test set name='TTT2' where id=3;
②session2 添加共享锁,排他锁都被挂起
15:42:39 TEST@mesorcl>lock table test in exclusive mode;
15:42:39 TEST@mesorcl>lock table test in share mode;
上述几种锁模式中,RS锁是限制最少的锁,X锁是限制最多的锁。它们的兼容关系如下
四、其他锁的信息
--库缓存结构----
https://blog.csdn.net/cuiyan1982/article/details/78487854
http://blog.itpub.net/26736162/viewspace-2140856/
https://www.cnblogs.com/heart-king/p/5235406.html
开发多用户、数据库驱动的应用时,最大的难点之一是:一方面要力争取得最大限度的并发访问,与此同时还要确保每个用户能以一致的方式读取和修改数据。为此就有了锁定(locking)机制,这也是所有数据库都具有的一个关键特性,oracle在这方面更是技高一筹。
5.1 什么是锁
锁(lock)机制用于管理对共享资源的并发访问。注意,这里说的是“共享资源”而不是“数据库行”。Oracle会在行级对表数据锁定,不过oracle也会在其他多个级别上使用锁,从而对多种不同的资源提供并发访问。例如,执行一个存储过程时,过程本身会以某种模式锁定,以允许其他用户执行这个过程,但是不允许另外的用户以任何方式修改这个过程。数据库中使用锁是为了支持对共享资源进行并发访问,与此同时还能提供数据完整性和一致性。
需要了解的是有多少种数据库,其中就可能有多少种实现锁定的方法。你可能对某个特定的关系型数据库管理系统(RDBMS)的锁定模型有一定的经验,但是每个数据库中对实现锁定的方式都大相径庭。
在oracle中,你会了解到下面几点:
1.事务是每个数据库的核心,他们是好东西。
2.应该延迟到适当的时刻才提交。不要太快提交,以避免对系统带来压力。这是因为,如果事务很长或很大,一般不会对系统有压力。相应的原则是:在必要时才提交,事务的大小只应该根据业务逻辑来定。
3.只要需要,就应该尽可能长时间地保持对数据所加的锁。这些锁是你能利用的工具,而不是然给你退避三舍的东西。锁不是稀有资源(而在比如sqlserver中,这样做是疯狂的,会极大的降低性能)。
4.在oracle中,行级锁没有相关的开销,根本没有。不论你是有1个行级锁,还是1000000个行级锁,专用于锁定这个信息的资源数是一样的。当然,与修改1行数据相比,修改1000000行要做的工作肯定多得多,但是对1000000行锁定所需的资源数与对1行锁定所需的资源完全相同,这是一个固定的常量。
5.不要以为锁升级“对系统更好”(例如,使用表锁而不是行锁)。在oracle中,锁升级对系统没有任何好处,不会节省任何资源。
6.可以同时得到并发性和一致性。每次你都能快速而准确地得到数据。数据读取器不会被数据写入器阻塞。数据写入器也不会被数据读取器阻塞。这是oracle与大多数其他关系数据库之间的根本区别之一。
5.2 锁定问题
讨论oracle使用的各种类型的锁之前,先了解一些锁定问题会有好处,其中很多问题都是因为应用设计不当,没有正确使用数据库锁定机制产生的。
5.2.1 丢失更新
丢失更新(lost update)是一个经典的数据库问题。简单地说,出现下面的情况时就会发生丢失更新。
(1)会话session1中的一个事务获取(查询)一行数据,放入本地内存,并显示给一个最终用户user1.
(2)会话session2中的另一个事务也获取这一行,但是将数据显示给最终用户user2.
(3)User1使用应用修改这一样,然该应用更新数据库并提交。会话session1的事务现在已经执行。
(4)User2也修改这一样,让应用更新数据库并提交。会话session2的事务现在已经执行。
许多工具可以保护你避免这种情况,如oracle forms和apex,这些工具能确保从查询记录的那个时刻起,这个记录没有改变,而且对他执行任何修改时都会将其锁定,但是其他程序做不到这点(如手写的VB或java)。实际上就是要使用某种锁定策略,共有两种锁定策略:悲观锁定或乐观锁定。
5.2.2 悲观锁定
用户在屏幕上修改值之前,这个锁定方法就要起作用。例如,用户一旦有意对他选择的某个特定行执行更新,就会放上一个行级锁。这个行锁会持续到程序对行的修改提交。
悲观锁定(pessimistic locking)仅用于有状态(stateful)或有连接(connected)环境,也就是说,你的应用与数据库由一条连续的连接,而且至少在事务生存期中只有你一个人使用这条连接。这是20世纪90年代的一种流行做法。每个应用格斗得到数据库的一条直接连接,这条连接只能由该实例使用,这种采用有状态的连接方法已经不太常见了。
我们可以使用select * … for update来显式的获取锁定。
5.2.3 乐观锁定
第二种方法称为乐观锁定(optimistic locking),即把所有锁定都延迟到即将执行更新之前才做。这种锁定方法在所有环境中都行得通,但是采用这种方法的话,执行更新的用户“失败”的可能性会加大。这说明,这个用户要更新它的数据行时,发现数据已经修改过,所以他必须从头再来。可以使用select for update nowait来验证行是否未被修改,并在即将update之前锁定来避免被另一个会话阻塞。
这里说下select for udate和select for update nowait/wait(n)
前者会主动获取锁,如果已经被别人获得,则一直阻塞等待。后者则无论获得锁还是不获得都会立刻或等待n秒后返回。获得锁后都是执行了显式或隐式的commit或rollback后释放锁。
实现乐观并发控制的方法有很多种。比如:
1.使用一个特殊的列,这个列由一个数据库触发器或应用程序代码维护,可以告诉我们记录的最新“版本号”。
如果应用要实现乐观并发控制,只需要保存这个附加列的值。应用验证请求更新那一刻数据库中这一列的值与最初读取的值是否匹配,如果两个值相等,则说明这一行未被修改过。
2.使用一个校验或散列值,这是使用原来的数据计算得出的。
这个与前面的版本列方法很类似,不过在此要使用基数据本身来计算一个虚拟的版本列。
5.2.4 乐观锁定还是悲观锁定
那么哪种方法更好呢?根据Tom的经验,悲观锁定在oracle中工作地非常好,而且与乐观锁定相比,悲观锁定有很多优点。不过,它需要与数据库有一条有状态的连接,如客户/服务器连接,因为无法跨连接持有锁。正是因为这一点,在当前的许多情况下,悲观锁定不太现实。过去,客户/服务器应用可能只有数十个或数百个用户,对于这些应用,悲观锁定是不二选择。不过,如今对大多数应用,tom都建议采用乐观并发控制。
5.2.5 阻塞
如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。这样一来,请求的会话会被阻塞,他会挂起,直到持有锁的会话放弃锁定的资源。几乎在所有情况下,阻塞都是可以避免的。
数据库有5条常见的DML语句可能会阻塞,具体是:insert,update,delete,merge和select for update。对于一个阻塞的select for update,很简单,只需要增加nowait子句就不阻塞了。我们看下另外4条DML语句,看看他们为什么不应阻塞,如果真的阻塞了应该如何修正。
1. 阻塞的insert
Insert阻塞的情况不多见。最常见的情况时,有一个带主键的表或表上有唯一约束。但有两个会话试图用同样的值插入一行。如果是这样,其中一个会话就会阻塞,直到另一个会话提交或回滚为止;如果另一个会话提交,那么阻塞的会话会受到一个错误,指出存在一个重复值;倘若另一个会话回滚,阻塞的会话则会成功。
如果应用允许最终用户生成主键/唯一列值,往往就会发生insert阻塞。为避免这种情况,最容易的做法是使用一个序列或SYS_GUID()生成主键/唯一列值。序列(sequence)内建函数设计为一种高度并发的方法,用在多用户环境中生成唯一键。
2. 阻塞的merge、update和delete
在一个交互式应用中,可以从数据库查询某个数据,允许最终用户处理这个数据,再把它“放回”到数据库中,此时如果update或delete阻塞,就说明你的代码中可能存在一个丢失更新问题,如果真这样,那也说明你的代码中存在bug。你试图update其他人正在更新的行。通过使用select for update nowait查询可以避免这个问题,这个查询能做到:
1.验证自从你查询数据之后数据未被修改(防止丢失更新)
2.锁住行(防止update 或delete被阻塞)。
5.2.6 死锁
如果有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。根据tom的经验,导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新)。在以下3种情况下,oracle在修改父表后会对子表加一个全表锁。
1. 如果更新了父表的主键,由于外键上没有索引,所以子表会被锁住。
2. 如果删除了父表中的一行,整个子表也会被锁住(由于外键上没有索引)。
3. 如果合并到父表,整个子表也会锁住(没有外键上的索引)。注意这一点只是用oracle 9i和10g,在11g开始不再成立。
但是,只要对外键加索引,这一切问题都解决了。
什么时候不需要对外键加索引呢?一般是当完全满足以下3个条件时:
1.没有从父表删除行
2.没有更新父表的唯一键/主键值
3.没有从父表联接子表
5.2.7 锁升级
出现锁升级(lock escalation)时,系统会降低锁的粒度。例如,数据库系统可以把一个表的100个行级锁变成一个表级锁。如果数据库认为锁是一种稀有资源,而且想避开锁的开销,这些数据库会频繁使用锁升级。注意:oracle从来不会升级锁。
5.3 锁类型
Oracle主要有3种锁。
1. DML锁(DML lock):DML代表数据操纵语言(Data Manipulation Language)。一般来讲,这表示select,insert,update,merge和delete语句。DML锁机制允许并发执行数据修改。
2. DDL锁(DDL lock):DDL代表数据定义语言(Data Definition Language),如create和alter语句等。DDL锁可以保护对象结构定义。
3. 内部锁和闩:oracle使用这些锁来保护其内部数据结构。例如,oracle解析一个查询并生成优化的查询计划时,他会把库缓存“临时闩”,将计划放在那里,以供其他会话使用。闩(latch)是oracle采用的一种轻量级的低级串行化设备,功能上类似于锁。不要被“轻量级”这个词搞糊涂或蒙骗了,你会看到,闩是数据库中导致竞争的一个常见原因。轻量级指的是latch的实现,而不是latch的作用。
5.3.1 DML锁
DML锁用于确保一次只有一个人能修改某一行,而且你正在处理一个表时别人不能删除这个表。在你工作时,oracle会透明程度不一地为你加这些锁。
1.TX锁
事务发起第一个修改时会得到TX锁(事务锁),而且会一直持有这个锁,直至事务执行提交或回滚。TX锁用作一种排队机制,使得其他会话可以等待这个事务执行。
在oracle中,闩为数据的一个属性。Oracle并没有一个传统的锁管理器,不会用锁管理器为系统中锁定的每一行维护一个长长的列表。不过,其他的许多数据库却是这样做的,对这些数据库来说,锁是一种稀有资源。
在oracle中的锁定过程如下:
(1) 找到想锁定的那一行的地址。
(2) 到达那一行。
(3) 锁定这一行
2. TM(DML Enqueue)锁
TM锁用于确保在修改表的内容时,表的结构不会改变。例如,如果已经更新了一个表,会得到这个表的一个TM锁。这会防止另一个用户在该表上执行DROP或ALTER命令。如果有表的一个TM锁,而另一位用户试图在这个表上执行DDL,就会得到报错ORA-00054:resource busy and acquire with NOWAIT specified
尽管每个事务只能得到一个TX锁,但是TM锁则不同,修改了多少个对象就能得到多少个TM锁。
5.3.2 DDL锁
在DDL操作中会自动为对象加上DDL锁,从而保护这些对象不会被其他会话所修改。例如,如果执行一个DDL操作alter table T,表T上就会加一个DDL锁,以防止其他会话得到这个表的DDL锁和TM锁。
在DDL语句执行期间会一直持有DDL锁,一旦操作执行就立即释放DDL锁。实际上,通常会把DDL语句包装在隐式提交(或提交/回滚对)中来执行。由于这个原因,在oracle中DDL一定会提交。每条create,alter等语句实际上都如下执行(伪代码):
begin
commit;
DDL-statement;
commit;
exception
when others then rollback;
end;
因此,DDL总会提交(即使提交不成功也会如此)。DDL一开始就提交。
有以下3种类型的DDL锁:
1.排他DDL锁(Exclusive DDL lock):这会防止其他会话得到他们自己的DDL锁或TM锁。这说明,在DDL操作期间可以查询一个表,但是无法以任何方式修改这个表。
2.共享DDL锁(Share DDL lock):这些所会保护所引用的结构,使之不会被其他会话修改,但是允许修改数据。
3.可中断解析锁(Breakable parse locks):这些锁允许一个对象向另外某个对象注册其依赖性。如果在被依赖的对象上执行DDL,oracle会查看已经对该对象注册了依赖性的对象列表,并使这些对象无效。因此,这些锁是可中断的,他们不能防止DDL出现。
5.3.3 闩(latch)
Latch是轻量级的串行化设备,用于协调对共享数据结构、对象和文件的多用户访问。
Latch就是一种锁,设计为只保持极短的一段时间(例如,修改一个内存中数据结构所需的时间)。Latch用于保护某些内存结构,如数据库快缓冲区或共享池中的库缓存。一般会在内部以一种“愿意等待”模式请求latch。这说明,如果latch不可用,请求会话会睡眠很短的一段时间,并在以后再次尝试这个操作。还可以采用一种“立即”(immediate)模式请求其他latch,这与select for update nowait的思想很相似。
Oracle使用诸如“测试和设置”(test and set)以及“比较和交换”(compare and swap)之类的原子命令来处理latch。
1. 闩“自旋”
关于latch还要了解一点,latch是一种锁,锁是串行化设备,而串行化设备会妨碍可扩展性。如果你的目标是构建一个能在oracle环境中很好地扩展的应用,就必须寻找合适的方法和解决方案,尽量减少所需执行的闩定的量。
等待latch可能是一个代价很高的操作。如果latch不是立即可用的,我们就得等待,在一台多cpu机器上,我们的会话就会自旋(spin),也就是说,在循环中反复地尝试来得到latch。出现自旋的原因是,上下文切换的开销很大,我们就会一直呆在cpu上,并立即再次尝试,而不是先睡眠放弃cpu。
同时,经过对比是否使用绑定变量,发现使用绑定变量的查询比不适用绑定变量耗费的硬件资源(cpu)少一个数量级,比如在解析阶段和等待latch阶段都节省很多资源。
补充自旋锁:
自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,即在标志寄存器中关闭/打开中断标志位,不需要自旋锁)。
何谓自旋锁?它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。