首页 > 代码库 > Oracle 锁机制

Oracle 锁机制

以前虽然在网上看到很多关于Oracle锁机制的描述,但总感觉哪里有缺陷不适合自己,因此花了点时间参考Tom Tyke的《Oracle 9i/10g/11g编程艺术》一书整理了一下Oracle锁相关的知识。

声明:本文属于个人读后感,内容不保证100%正确。

一、Oracle数据库的锁类型:

根据保护的对象不同,Oracle数据库锁可以分为以下几大类:    
1、DML锁(data locks,数据锁),用于保护数据的完整性;    
2、DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;    
3、内部锁和闩(internal locks and latches),保护数据库的内部结构。 
二、接下来依次讨论以上三种锁结构:
 
1.DML锁
DML锁主要包括TM锁和TX锁,其中TM锁称为意向锁或表级锁,TX锁称为行级锁或事务锁。
1.1 TM锁
TM锁包含如下类型:
技术分享

TM锁的兼容性如下:

技术分享

1.2 TX锁

TX的本义是Transaction(事务),当一个事务第一次执行数据更改(Insert、Update、Delete)或使用SELECT… FOR UPDATE语句进行查询时,它即获得一个TX(事务)锁,直至该事务结束(执行COMMIT或ROLLBACK操作)时,该锁才被释放。
在同一个事务中,无论是锁定一行,还是一百万行,对于Oracle来说TX锁的开销是一样的。这点可能与其他数据库很不一样,原因如下:
在Oracle的每行数据上,都有一个标志位来表示该行数据是否被锁定。这样就极大的减小了行级锁的维护开销,也不可能出现锁升级。数据行上的锁标志一旦被置位,就  表明该行数据被加X锁。
Oracle在数据行上没有S锁,换句话说就是TX锁只有一种--行级独占锁。(注意TX锁在v$lock的lmode也是6,但是这个6与TM锁的6号X锁是完全不同的两个东西)
 

1.3 举例说明

当发出一个DML命令后会话获取一个3号的TM锁,和一个针对特定行的6号TX锁。
行级只有X锁,且锁模式为6,再次重申这里的6并不是指TM的6号表锁。此外Oracle一个事务中只会获取一个TX锁,但有多少个表对象就会获取多少个TM表级锁。
验证如下:
技术分享

查询锁的语句为:

select sid,type,id1,lmode,request,block from v$lock l where sid in (select session_id from v$locked_object) and type in (‘TM‘, ‘TX‘) order by 1;

1.4 DML锁的总结:

读永远不会阻止写。但有唯一的一个例外,就是select ...for update。
写永远不会阻塞读。
当一行被修改后,Oracle通过回滚段提供给数据的一致性读。
注意:以上说明的读和写不会互相阻塞是指在DML锁级别不会,但读写之间依然会发生数据库内部闩锁的争用。具体详见数据库内部闩锁的博文。

 
2.DDL锁

重点:DDL是保护表结构定义的。
DDL命令发出时,Oracle会自动在被处理的对象上添加DDL锁定,从而防止对象被其他用户所修改。当DDL命令结束以后,则释放DDL锁定。DDL锁定不能显式的被请求,只有当对象结构被修改或者被引用时,才会在对象上添加DDL锁定。
并不是所有DDL都会触发DDL锁,例如现在的创建索引语句,就只会获取一个S模式的TM锁,因此不会阻塞读。而online模式创建索引的语句则只会获取一个RS模式的TM锁,因此连DML也不会被阻塞。但是事务应尽快提交,原因参见博文:http://blog.itpub.net/7417681/viewspace-1061318/
需要注意的是DDL总会提交,即便是执行不成功也是如此,因此如果在事务中执行了DDL语句会导致所有事物被提交。验证很容易,在一个窗口执行一条delete然后执行DDL,你会发现记录被不可逆转的删除了,RollBack无效。因此针对事务中的DDL请务必使用自治事务实现。
DDL锁有3种:(第一种就是X模式的TM锁)
2.1 排他DDL锁
一般对表的DDL语句都会获取一个X模式的TM锁,这是为什么在表结构更改时只能查询不能修改的原因。
2.2 共享DDL锁
共享DDL锁的常见情形为创建存储过程时,会尝试为所有涉及到的表添加共享DDL锁,这会允许类似的DDL操作并发,但会阻止所有想要获取排他DDL锁的会话(即更改表结构的会话)。
2.3 可中断解析锁
会话解析一条语句时,对于该语句引用的每一个对象都会施加解析锁,这个目的是如果以某种方式删除或修改了引用对象,可以将共享池中已经解析的缓存语句无效刷出。
 
3.内部闩锁机制(略)
详见博文,关于Oracle buffer pool/shared pool的内部闩锁机制的实现。

 

Oracle 锁机制