打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ORACLE锁

开发多用户、数据库驱动的应用时,最大的难点之一:一方面要力争取得最大限度的并发访问,与此同时还要确保每个用户能以一致的方式读取和修改数据;为此就有了锁定(locking)机制。
锁(lock)机制用于管理对共享资源的并发访问,同时还能提供数据完整性和一致性。

 

有多少种数据库,其中就可能有多少种实现锁定的方法。时刻记住以下两点:
1、所有数据库本质上都不同。
2、为一个新的数据库平台设计应用时,对于数据库如何工作不能做任何假设。
如SQL Server利用聚簇索引,就能按聚簇键的顺序在整个表中插入行(而不是只在表的末尾插入),以改善SQLServer数据库的并发性。而且默认情况下,SQLServer每执行一条语句后就会立即提交或回滚。这样为了得到更大的并发性,但是会破坏事务完整性。

 

在Oracle中
事务是每个数据库的核心
在必要时才提交,不要太快提交,以避免对系统带来压力。事务的大小只应该根据业务逻辑来定。
只要需要,就应该尽可能长时间地保持对数据所加的锁。
行级锁没有相关的开销,根本没有。不论你是有1个行锁,还是1000000个行锁,专用于锁定这个信息的“资源”数都是一样的。
不同级别的锁的开销是一样的
数据读取器不会被数据写入器阻塞。数据写入器也不会被数据读取器阻塞。

 

一、锁定问题:丢失更新;需要使用某种锁定策略,共有两种锁定策略:悲观锁定或乐观锁定。
1、悲观锁定;在试图更新之前我们就把行锁住了。
2、乐观锁定;锁定都延迟到即将执行更新之前才做。执行更新的失败可能性会加大。

实现方法有很多,以下介绍四种:
 a、在应用中同时保留旧值和新值,存储行的所有“前”(before)映像。
 b、使用版本列的乐观锁定;版本维护:应用、存储、触发器(开销较大)。
 c、使用校验和的乐观锁定;计算散列或校验和有很多方法。
 计算散列或校验和是一个CPU密集型操作,相当占用CPU。如果从网络开销角度看,计算散列或校验和只需在网络上传输相当小的散列值,而不是行的完整的前映像和后映像。 
 d、使用 ORA_ROWSCN的乐观锁定;Oracle10g函数ORA_ROWSCN,不仅很小(类似于散列),计算时不是CPU密集型。
 它的工作与版本列技术很相似,但可由Oracle自动执行,而不需要在表中增加额外的列,也不需要额外的更新/维护代码来更新这个值。ORA_ROWSCN默认是在块级维护,一个块上的多行会共享相同的ORA_ROWSCN值,除非在创建表时,启用ROWDEPENDENCIES支持在行级维护ORA_ROWSCN。

 

(一)阻塞
如果一个会话持有某个资源的锁,另一个会话也请求这个资源,就会出现阻塞(blocking);在一个交互式应用中被阻塞,很有可能同时存在丢失更新。
数据库中有5条常见的DML语句可能会阻塞:INSERT、UPDATE、DELETE、MERGE和SELECT FORUPDATE。
1、阻塞的SELECT FOR UPDATE,解决方案只需增加NOWAIT子句即可。这样应用会告知调用者,这一行已经锁定。
通过使用SELECT FOR UPDATE NOWAIT查询能做到:
 a、验证自从你查询数据之后数据未被修改(防止丢失更新)。
 b、锁住行(防止UPDATE或DELETE被阻塞)。
2、阻塞的INSERT;不多见。
 最常见的情况:
 a、一个带主键或者有惟一约束的表,但有两个会话试图用同样的值插入一行。让用户生成主键或惟一约束即可避免;也可通过内置的DBMS_LOCK包实现手工锁解决,但不推荐,因其开销大。
 b、多个表通过引用完整性约束相互链接。当子表所依赖的父表正在创建或删除,对子表的插入可能会阻塞。在应用中注意先后。
3、阻塞的Merge、Update和Delete。
不论是悲观锁定还是乐观锁定都可以利用SELECT FOR UPDATENOWAIT查询来验证行未被修改。悲观锁定会在用户有意修改数据那一刻使用这条语句。乐观锁定则在即将在数据库中更新数据时使用这条语句。

 

(二)死锁
A表有两条数据1和2,两个会话:会话a和会话b
阻塞:会话a更新数据1,会话b更新数据2;若会话b同时更新数据1则出现阻塞;若会话a也同时更新数据2是出现死锁。
阻塞时前一个事务提交或回滚即可继续;死锁则需牺牲一个更新,让其更新回滚。
Oracle认为死锁很少见,所以每次出现死锁时它都会在服务器上创建一个跟踪文件。
导致死锁原因:
1、外键未加索引。
2、表上的位图索引遭到并发更新。
在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁:
1、如果更新了父表的主键(倘若遵循关系数据库的原则,即主键应当是不可变的),由于外键上没有索引,所以子表会被锁住。
2、如果删除了父表中的一行,整个子表也会被锁住(由于外键上没有索引)。
在Oracle9i及以上版本中,全表锁都是短期的,仅在DML操作期间存在,而不是在整个事务期间都存在。
如果存在未加索引的外键,只需对外键加索引,死锁(以及大量其他的竞争问题)都不会出现。
,当满足以下条件时不需要加索引
1、没有从父表删除行。
2、没有更新父表的惟一键/主键值(当心工具有时会无意地更新主键!)。
3、没有从父表联结子表(如DEPT联结到EMP)。

 

(三)锁升级
Oracle不会升级锁,但会执行锁转换(lock conversion)或锁提升(lock promotion)。
比如用FORUPDATE子句从表中选择一行,就会创建两个锁。一个锁放在所选的行上(排他锁;任何人都不能以独占模式锁定这一行)。另一个锁是ROWSHARE TABLE锁,放在表本身上,防止其他会话在表上放置一个排他锁。

 

二、锁类型
Oracle中的锁定过程如下:
(1) 找到想锁定的那一行的地址。
(2) 到达那一行。
(3) 通过数据的闩属性锁定这一数据行(该行若已经锁定,则等待锁住它的事务结束,除非使用了NOWAIT选项)。
ORACLE通过数据本身来管理行锁定和事务信息。
Oracle中主要有3类锁,具体是:
(一)DML锁(DML lock):DML代表数据操纵语言(Data ManipulationLanguage)。包含SELECT、INSERT、UPDATE、MERGE和DELETE语句。DML锁机制允许并发执行数据修改。DML锁(DMLLock)确保一次只有一个人能修改某一行,且处理一个表时别人不能删除这个表。
1. TX锁(事务锁)
事务发起第一个修改时会得到TX锁(事务锁),而且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。
2. TM (DML Enqueue)锁
TM锁(TM lock)用于确保在修改表的内容时,表的结构不会改变。
(二)DDL锁(DDL lock):DDL代表数据定义语言(Data DefinitionLanguage),如CREATE和ALTER语句等。DDL锁可以保护对象结构定义。
DDL默认总会提交。有3种类型的DDL锁:
1. 排他DDL锁(Exclusive DDL lock):这会防止其他会话得到它们自己的DDL锁或TM(DML)锁。
2. 共享DDL锁(Share DDL lock):保护所引用对象的结构不被其他会话修改,但是允许修改数据。
3. 可中断解析锁(Breakable parselocks):允许一个对象(如共享池中缓存的一个查询计划)向另外某个对象注册其依赖性。如果在被依赖的对象上执行DDL,Oracle会查看已经对该对象注册了依赖性的对象列表,并使这些对象无效。
通过DBA_DDL_LOCKS可查看DDL锁的信息;开发人员可通过这个视图发现测试或开发系统中某段代码无法编译时,将会挂起并最终超时。这说明有人正运行这段代码,可用该视图查看谁在运行。对于GRANTS和对象的其他类型的DDL也是一样。
同时可用SYS用户运行[ORACLE_HOME]/rdbms/admin目录下的catblock.sql脚本来安装相关锁视图。
(三)内部锁和闩:Oracle使用这些锁来保护其内部数据结构。例如,Oracle解析一个查询并生成优化的查询计划时,它会把库缓存“临时闩”,将计划放在那里,以供其他会话使用。闩(latch)是Oracle采用的一种轻量级的低级串行化设备,功能上类似于锁。闩是数据库中导致竞争的一个常见原因。轻量级指的是闩的实现,而不是闩的作用。用于协调对共享数据结构、对象和文件的多用户访问。
Oracle使用测试和设置(test and set)及比较和交换(compare andswap)之类的原子指令来处理闩。由于设置和释放闩的指令是原子性的,尽管可能有多个进程同时请求,但操作系统本身可保证只有一个进程能测试和设置闩。指令仅仅是一个指令而已,它执行得可能非常快。闩只保持很短的时间,而且提供了一种清理机制,万一某个闩持有者在持有闩时异常地死掉,通过PMON执行清理。
队列锁(enqueue是一种更复杂的串行化设备。与闩的区别在于,队列锁允许请求者排队等待资源。对于闩请求,请求者会话会立即得到通知是否得到闩。且对于队列锁,请求者会话会阻塞,直至真正得到锁。
闩是一种串行化设备,而串行化设备会妨碍可扩缩性。
等待闩是一个代价很高的操作,尝试得到闩过程会耗费大量的CPU时间。闩未能立即可用就得等待,若是多CPU机器,会话就会自旋(spin),即在循环中反复地尝试来得到闩。
(四)手动锁定和用户定义锁
介入这种锁定活动。有以下选择:
1.通过一条SQL语句手动地锁定行数据。如SELECT...FOR UPDATE语句就是手动锁定数据的一种主要方法。
2.通过DBMS_LOCK包创建我们自己的锁。如外部文件ORACLE不可协调。

 

附:有时数据库挂起,面对一个看上去无法解决的挂起问题,运行一个查询来检测外键是不是没有索引,并建议对导致问题的外键加上索引,就能很好地解决问题

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Oracle数据完整性和锁机制
第十三章 数据一致性和并发性
oracle事务与锁
oracle的锁与并发机制
事务与锁的一些总结(转)
MySQL在并发场景下的问题及解决思路
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服