oracle数据库的锁机制

一、并发访问带来的问题
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

1、丢失修改
事务T1和事务T2读入同一数据并修改,事务T2提交的结果破坏了事务T1提交的结果,导致事务T1的修改丢失。

2、读“脏”数据
事务T1修改某一数据,并将其写回磁盘,事务T2读取同一数据后,事务T1由于某种原因被撤销,这时事务T1修改过的数据恢复原值,事务T2读到的数据就与数据库中的数据不一致,事务T2读到的数据就是“脏”数据,即不正确的数据。

3、不可重复读
事务T1读取数据后,事务T2执行更新操作,使事务T1无法再现前一次读取结果。不可重复读的三种情况如下:
(1)事务T1读取某一数据后,事务T2对其做了修改,当事务1再次读该数据时,得到与前一次不同的值。
例如,T1读取B=100进行运算,T2读取同一数据B,对其进行修改后将B=200写回数据库。T1为了对读取值校对重读B,B已为200,与第一次读取值不一致。
(2)事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神秘地消失了。
(3)事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。(这也叫做幻读)

二、锁机制
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
oracle通过具有意向锁的多粒度封锁机制进行并发控制,保证数据的一致性。


1、锁的概念
锁是用来防止各个事务之间的相互影响,对并发访问进行控制,以保证数据一致性和完整性的一种机制

2、oracle锁的特点
(1)锁由Oracle自动管理,锁持续的时间等于被提交事务处理的时间
(2)单用户数据库不需要锁机制
(3)ORACLE中的锁是不受限制也不会自动升级的
(4)ORACLE中的查询语句是不会锁定数据的,前提是不带FOR UPDATE 子句的SELECT语句。ORACLE的查询是通过使用在撤销空间中所存储的数据被锁定之前的前映像来成功地执行的,这种方式提高了并发度,并保证了事务不会读取到脏数据

3、锁的类型
根据保护对象的不同,数据库锁可以分成5大类
(1)DML Locks(data locks,数据锁):用于保护数据的完整性和一致性
DML锁分为2种:TX锁(事务锁或行级锁)和TM锁(表级锁)。
(2)DDL Locks(dictionary locks,字典锁):用于保护数据库对象的结构(如表、视图、索引的结构定义)
DDL锁能防止在用DML语句操作数据库表时,对表进行删除,或对表的结构进行更改。DDL锁由Oracle自动加锁和释放。不能显式地给对象加DDL锁,即没有加DDL锁的语句
(3)Internal Locks 和 Latches(内部锁与闩):用于保护内部数据库结构
(4)Distributed Locks(分布式锁):用于OPS(并行服务器)中
(5)PCM Locks(并行高速缓存管理锁):用于OPS(并行服务器)中

4、意向锁
(1)意向锁的概念
意向锁的含义是如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对它的上层结点加意向锁。如果要封锁表的某个行,则也在该行所在的表上加上锁。这样的话在对整个表进行操作时,就不用遍历表里的所有行了。
如:对表中的任一行加锁时,必须先对它所在的表加意向锁,然后再对该行加锁。这样一来,事务对表加锁时,就不再需要检查表中每行记录的锁标志位了,系统效率得以大大提高。

(2)意向锁的类型
基本的锁类型(S、X)与意向锁类型(IS、IX)之间还可以组合出新的锁类型,这样数据库对象上所加的锁类型就可能有5种
共享锁(Share Locks,即S锁)
如果事务T对表A加上共享锁,则事务T可以读表A,但不能修改表A数据,其他事务也只能对表A加共享锁,但是不能加排他锁,保证了其他事务可以读表A数据,但是不能修改表A数据。
排它锁(Exclusive Locks,即X锁)
如果事务T对表A加上排他锁,则只允许事务T对表A数据的读取和修改,其他事务不允许对表A增加任何锁,知道事务T释放加在表A上的所有锁。
意向共享锁(IS)
如果对表加IS锁,表示该表中的某个行被加上了S锁。
意向排他锁(IX)
如果对表加IX锁,表示该表中的某个行被加上了X锁。
共享意向排它锁(SIX)
表示先对某个表加上S锁,然后再加上X锁,表示要读取整个表的数据,但是只对其中的一部分行做修改

5、oracle提供的5种数据锁
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。下面的5种锁类型与意向锁的5种类型是一一对应的。

(1)共享锁(S)
加锁命令:lock table in share mode;
在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。
(2)排它锁(X)
加锁命令:lock table in exclusive mode
在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。
(3)行级共享锁(RS)
通过select … from for update语句添加
同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。
(4)行级排它锁(RX)
当我们进行DML时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。
(5)共享行级排它锁(SRX)
加锁命令:lock table in share row exclusive mode
该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

6、悲观锁和乐观锁
(1)悲观锁
指在应用程序中显式地为数据资源加锁。悲观锁假定当前事务操纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前
事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它会影响并发性能,因此应该很谨慎地使用悲观锁。
(2)乐观锁
乐观锁假定当前事务操纵数据资源时,不会有其他事务同时访问该数据资源,因此完全依靠数据库的隔离级别来自动管理锁的工作。应用程序采用版本控制手段来避免可能出现的并发问题

7、数据库三级封锁协议
在运用X锁和S锁这两种基本封锁对数据对象加锁时,还需要约定一些规则。例如,何时申请X锁或S锁、持锁时间、何时释放等。这些规则称为封锁协议。通常使用三级封锁协议来在不同程度上解决并发操作的不正确调度带来的丢失修改、不可重复读和读“脏”数据等不一致性问题。
(1)一级封锁协议
事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。
一级封锁协议可防止丢失修改,并保证事务T是可恢复的。在一级封锁协议中如果仅仅是读数据不对其进行修改是不需要加锁的,所以不能保证可重复读和读“脏”数据
(2)二级封锁协议
事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放X锁。事务T在读取数据R之前必须先加S锁,读完后即可释放S锁。M级封锁协议不仅能够防止丢失修改,还可以防止读“脏”数据
(3)三级封锁协议
事务T在读取数据R之前必须先对其加S锁,在修改数据R之前必须先对其加X锁,直到事务结束后才释放所有锁。由于三级封锁协议强调及时读完数据A也不释放S锁,从而使别的事务无法更改数据A,三级封锁协议不仅防止了丢失修改和读“脏”数据,还能防止不可重复读

8、锁机制带来的问题
(1)死锁:两个事务(会话)都进入彼此等待对方锁定的资源时的一种停止状态
解决方法:"牺牲"一个会话,回滚一个会话的事务,使另一个会话事务继续执行
(2)阻塞:如果一个会话持有某个资源的锁,另一个会话再申请这个资源,就造成了堵塞

9、产生锁定模式的SQL语句
select                 模式:行级共享锁(RS)  允许RS、RX、SRX、S、X
insert                 模式:行级排他锁(RX)  允许RS、RX
update                 模式:行级排他锁(RX)  允许RS、RX
delete                 模式:行级排他锁(RX)  允许RS、RX
select ... for update  模式:行级共享锁(RS)  允许RS、RX、SRX、S

猜你喜欢

转载自blog.csdn.net/cc_0101/article/details/81873319
今日推荐