重点:DDL是保护表结构定义的。
当DDL命令发出时,Oracle会自动在被处理的对象上添加DDL锁定,从而防止对象被其余用户所修改。当DDL命令结束之后,则释放DDL锁定。
DDL锁定不能显式的被请求,只有当对象结构被修改或者被引用时,才会在对象上添加DDL锁定。
并非全部DDL都会触发DDL锁,例如如今的建立索引语句,就只会获取一个S模式的TM锁,所以不会阻塞读。而online模式建立索引的语句则只会获取一个2号的TM锁,所以连DML也不会被阻塞。
须要注意的是DDL总会提交,即使是执行不成功也是如此,所以若是在事务中执行了DDL语句会致使全部事物被提交。验证很容易,在一个窗口执行一条delete而后执行DDL,你会发现记录被不可逆转的删除了,RollBack无效。所以针对事务中的DDL请务必使用自治事务实现。
DDL锁有3种:
2.1 排他DDL锁 --即6号的TM锁(Exclusive DDL Locks)
通常对表的DDL语句都会获取一个X模式的TM锁,这是为何在表结构更改时只能查询不能修改的缘由。
2.2 共享DDL锁(Share DDL Locks)
共享DDL锁的常见情形为建立存储过程时,会尝试为全部涉及到的表添加共享DDL锁,这会容许相似的DDL操做并发,但会阻止全部想要获取排他DDL锁的会话(即更改表结构的会话)。
--我觉的能够认为这就是4号的TM表锁。
2.3 可中断解析锁(Breakable Parse Locks)
会话解析一条SQL或PLSQL代码块时,对于该语句引用的每个对象都会施加解析锁,目的在于:若是以某种方式删除或修改了引用对象,能够将共享池中已经解析的缓存语句无效刷出。
之因此叫作可中断解析锁,是由于这种锁优先级很低可能会被其余互斥DDL操做打断。
每一个SQL在解析时都会获取一个可中断解析锁,只要SQL语句还在shared pool中,这个锁就一直存在。
Library cache lock 和 Library cache pin就是属于可中断解析锁,lock是针对父游标句柄和子游标句柄的保护体,pin是针对父子游标的保护体。前者有三种模式:1 null,2 S,3 X 后者只有2 S,3 X两种模式。
Latches:
可译做闩或者栓,这是一种很是低级别的序列化结构,用于协调并发会话对于共享数据结构、文件等的访问。
闩能够防止并发会话破坏共享的内存资源,几个很是典型的场景是:
- 多个会话同时修改数据
- 读取的数据正在被其余会话修改
- 从新分配内存
可能在这里会和事务锁混淆,但事务锁是锁定逻辑结构的,如表和行,可是闩倒是锁定物理结构的,如内存中的数据块、执行计划链表等等。多个会话对于同一个对象的访问就须要闩来保护了,例如对于同一个数据块中不一样行的访问就须要latch来保护,而闩的存在时间是极短的,所以能够实现高并发(其实Oracle高并发并不是是真正的并发而是latch释放速度极快的串行访问)。
一般在SGA中一个latch能够保护多个对象,例如DBWn和LGWR进程从SGA中分配内存以便建立新的数据结构,为了防止冲突进程会使用一种叫作shared pool latch的闩来序列化分配操做,在内存分配完毕后其它进程可能会须要访问shared pool中的其余区域如library cache,此时闩只会锁住library cache而非整个shared pool。
一般状况下oracle进程获取闩的时间极短,一个简单的查询都会有成千上万次的闩的获取和释放,是彻底不能由用户控制的。
闩的数目的增多,意味着并发量增大,能够经过v$latch视图来查看闩的使用状况,包括每种闩被请求和等待的次数。
Mutex:(Mutual exclusion object)
能够译做互斥体,这种结构很相似于闩,区别在于一种mutex只保护一种对象,而一种闩一般会保护多种对象。
mutex的优点在于:
- mutex能够减小latch争用
- mutex比latch占用更少的内存
- share mode模式的mutex容许多个会话并发使用
其余内部锁:
这些是比mutex和latch更复杂的结构,oracle数据库使用如下几种内部锁:
1.Dictionary cache locks
2.File and log management locks
3.Tablespace and undo segment locks
这几种锁的解释有兴趣能够到官网看,平时基本观察不到,后两种基本都在多实例时出现。
拓展说明:
上边谈到了Library cache lock和Library cache
pin,这里稍微解释下:
1、首先咱们以Oracle 10.2以前版本做为基准来解释:主要来自于《Oracle8i Internal Services》一书的第四章
****************************************
Library cache的包含不少cache部分,它包含PLSQL代码块的、解析树、SQL执行计划等,它还包含一个由SQL引用的DIANA的数据库对象,此对象被用于进行PLSQL块的编译以及SQL解析和执行,尽管数据字典中也包含此类信息。此外library cache也包含例如同义词转换、依赖追踪等信息,固然还有library cache lock/pin等内存闩锁。
Library cache lock和Library cache
pin属于可中断解析锁,Library cache lock有NULL、S、X三种模式,Library cache pin有S和X两种模式,在解析SQL时会话获取S模式的Library cache lock,解析完毕后转为NULL模式。若是有DDL操做更改了语句涉及的数据库对象,那么依赖于此数据库对象的全部library cache objects都会失效,失效过程就是失去NULL模式的library cache lock的过程。
****************************************
接下来先放一张图:
这是library cache中主链表的简易结构图,每一个hash bucket对应一个父游标句柄的链表,LCO表示library cache objects,是父游标或者子游标。父子游标是一对一或者一对多的关系。
在了解了以上基本常识的状况下,再来看涉及的内存栓锁:
进行硬解析的会话须要获取library cache latch(只有独占模式,无队列)来生成父游标句柄,待添加X模式library cache lock后释放library cache latch进行父游标句柄构造,构造父游标句柄完毕后获取X模式的library cache pin来构造父游标,接下来获取X模式的library cache lock生成子游标句柄,最后获取X模式library cache pin构造子游标完成硬解析。
若是是在已经存在的父游标上进行硬解析那么就会添加S模式的父游标句柄library cache
lock来获取X模式的父游标library cache pin,以后获取X模式的library cache lock/pin完成硬解析。
软解析时则先获取S模式的父游标句柄library cache lock,而后获取S模式父游标library cache
pin、S模式子游标句柄library cache lock和S模式子游标library cache pin。
2、接下来讨论10.2以后的的变化:
library cache pin结构被Cursor:xxx类型的mutex取代,而在11.1以后library cache latch结构也被library cache:mutex xxx类型的mutex取代了。
那么全新的SQL硬解析时首先会在library cache:mutex X的保护下获取X模式的library cache lock,而后释放mutex并构造父游标句柄,以后获取Cursor:pin X构造父游标,而后获取子游标句柄library cache lock构造子游标句柄并释放父游标的Cursor:pin X,最后获取Cursor:pin X完成子游标的构造从而完成硬解析。
若是是已经存在的父游标进行硬解析,那么首先在library cache:mutex X的保护下获取S模式的library
cache lock,以后获取Cursor:pin S来pin住父游标,而后获取X模式的library cache lock构造子游标句柄并释放父游标mutex,最后获取Cursor:pin X构造子游标完成硬解析。
若是是软解析那么首先在library
cache:mutex X的保护下获取S模式的library cache lock,以后获取Cursor:pin S来pin住父游标,最后依次找到子游标句柄和子游标。
若是发生了Cursor:pin S wait on X,那么意味着有硬解析在发生,而且可能存在较高的version count,致使此父游标句柄下的全部游标没法拿到Cursor:pin S。还有一种状况是游标涉及的LCO发生了DDL致使全部句柄失效,此时须要进行从新编译获取X模式的子游标mutex,所以其余会话发生Cursor:pin S wait on X等待。
一样的library cache lock等待也意味着存在硬解析,只有硬解析才会获取X模式的library cache lock,因为library cache lock的获取须要mutex的保护,相应的mutex等待也会伴生,多是library cache:mutex X或者Cursor:xxx类型的mutex,这取决于library
cache lock的等待是在父游标句柄仍是子游标句柄上,子游标句柄较为常见。
最后重要说明:
以上全部观点除来自书本的那段以外,都是基于buffer cache链表的查找方式进行类推解释的,都是基于latch/mutex是锁获取与释放的保护体来解释的,都是基于修改底层结构须要在上层添加X模式锁来解释的,都是基于mutex是一种极端稀缺的资源来解释的,极可能是错的,我这里只是为了创建初步的架构方便理解,就算是错的对我来讲也无所谓。
总结一下本身的观点:
DML和除可中断解析锁以外的DDL锁就是保护逻辑结构的结构体,而library cahce lock/pin、latch和mutex则是保护内存中物理结构的结构体,抛开DML锁,通常来讲在内存中获取内存锁都须要latch和mutex的保护,常见的场景就是library cache中Library cache lock的获取须要library cache:mutex X的保护,以及Buffer pool中的buffer pin 须要cbc latch保护住hash bucket中涉及到本SQL的链表头。
从名字上就能够看出latch和mutex的保护对象,cursor: xxx这种mutex保护的是游标, cbc latch保护的则是cache buffer chain链表,library cahce:mutex(之前叫library cache latch)则是用于保护library cache的,具体说来也是hash bucket的父游标句柄链表,以此来获取parent cursor handler上的library cache lock。
Oracle官网已经没有太多更详细的关于内部闩锁的资料,更详细的关于内部latch和mutex的运做机制和种类,参考吕海波《Oracle内核技术揭秘》和Steve Adams的《Oracle 8i Internal Services》一书。