ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Oracle Database基础学习笔记 之 锁

Oracle Database基础学习笔记 之 锁

原创 Linux操作系统 作者:wlot378 时间:2012-04-01 15:57:23 0 删除 编辑

============================================================
Oracle Database基础学习笔记 之 锁
参考资料:《Oracle 9i & 10g编程艺术-第6章 锁》
--by 王磊/菜小小~@  2011-5-4 9:06 2012-4-1 15:56
============================================================


数据库中使用锁是为了支持对共享资源进行并发访问(使对这些共享资源的并发性访问串行化),同时还能提供数据完整性和一致性

Oracle中事物在必要时才提交,事务的大小只应该根据业务逻辑来定;

在 Oracle 中,只要需要,就应该尽可能长时间地保持对数据所加的锁;

在 Oracle 中,行级锁没有相关的开销;

在 Oracle 中,可以同时得到并发性和一致性;


悲观锁定

悲观锁定( pessimistic locking )仅用于有状态( stateful )或有连接( connected )环境,在试图更新之前我们就把行锁住了,因为我们很悲观,对于这一行能不能保持未改变很是怀疑。

  • 使用悲观锁定后可以非常安全地修改这一行,且不会覆盖其他人所做的修改,因为已经验证了在最初读出 数据后以及对数据锁定之前数据没有改变。
  • 用 FOR UPDATE NOWAIT 锁定这一行实现悲观锁定,能避免丢失更新,但是有可能被阻塞


乐观锁定

乐观锁定( optimistic locking )把所有锁定都延迟到即将执行更新之前才做,即我们会修改屏幕上的信息而不要锁。因为我们很乐观,认为数据不会被其他用户修改;因此,会等到最后一刻才去看我们的想法对不对。

几种乐观锁定的实现方法:

  • 在应用中同时保留旧值和新值,然后在更新数据时使用如下的更新语句;

Update table

Set column1 = :new_column1, column2 = :new_column2, ....

Where primary_key = :primary_key

And column1 = :old_column1

And column2 = :old_column2

...

  • 使用附加列,维护版本信息:如果应用要实现乐观并发控制,只需要保存这个附加列的值,而不需要保存其他列的所有  前  映 像 。应用只需验证请求更新那一刻,数据库中这一列的值与最初读出的值是否匹配。如果两个值相等,就说明这一行未被更新过;
  • 使用校验和或散列值;将对变长输入串(即数据)通过单向散列函数转换得到的一个定长的输出串(即散列值)充当输入数据的一个惟一标识符(就像指纹一样),把从数据库读出数据时得到的散列或校验和值与修改数据前得到的散列或校验和值 进行比较来验证数据是否被修改;
  • 使用新增的 Oracle 10g 特性 ORA_ROWSCN:使用内置的 ORA_ROWSCN 函数由 Oracle 自动执行,而不需要在表中增加额外的列,也不需要额外的更新 / 维护代码来更新这个值,更新数据时要验证 SCN 未修改过;

注:

除非你创建表时支持在行级维护 ORA_ROWSCN ,否则 Oracle 会在块级维护。即默认情况下,一个块上的多行会共享相同的 ORA_ROWSCN 值;

将SCN转换为墙上时钟时间可使用scn_to_timestamp


阻塞

如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞( blocking ),请求的会话会  挂起  ,直至持有锁的会话放弃锁定的资源;

5 条可能导致阻塞的DML语句:INSERT 、 UPDATE 、 DELETE 、 MERGE 和 SELECT FOR UPDATE;

  • 阻塞的 INSERT

俩会话试图用同样的值向一个带主键约束或唯一性约束的表插入一行---->使用sequence 使用手工锁(内置DBMS_LOCK包);

  • 阻塞的 Merge 、 Update 和 Delete

试图 UPDATE (更新)其他人正在更新的行(换句话说, 有人已经锁住了这一行)。通过使用 SELECT FOR UPDATE NOWAIT 查询可以避免这个问题,


死锁

  • 如果你有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁( deadlock )
  • ORA-00060: deadlock detected while waiting for resource
  • 经验:导致死锁的头号原因是外键未加索引,第二号原因是表上的位图索引遭到并发更新
  • 删除父表中的一行可能导致子表被锁住:如果删除父表 P 中的一 行,那么在 DML 操作期间,子表C就会锁定,这样能避免事务期间对 C 执行其他更新(当然,这有一个前提,即没有人在修改 C ;如果确实已经有人在修改 C ,删除会等待)。此时就会出现阻塞和死锁问题。


锁类型(按保护对象分类)

Oracle 中的锁定过程:

  1. (1) 找到想锁定的那一行的地址。
  2. (2) 到达那一行。
  3. (3)锁定这一行(如果这一行已经锁定,则等待锁住它的事务结束,除非使用了 NOWAIT 选项,如果数据还没有被锁定,则对其锁定)

DML 锁(DML lock):data locks 数据锁,用来保护数据的完整性和一致性

  • DML锁机制允许并发执行数据修改,用于确保一次只有一个人能修改某一行,而且你正在处理一个表时别人不能删除这个表;
  • DML锁主要包括TM锁(表级锁)TX锁(事务锁或行级锁,)
  • 当Oracle执行delete,update,insert,select for update  DML语句时,oracle首先自动在所要操作的表上申请TM类型的锁,防止其他会话在这个对象上做ddl语句。当TM锁获得后,再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位(lb 即lock bytes)进行置位。在记录被某一会话锁定后,其他需要访问被锁定对象的会话会按先进先出的方式等待锁的释放(对于select操作而言,并不需要任何锁,所以即使记录被锁定,select语句依然可以执行,实际上,在此情况下,oracle是用到undo的内容进行一致性读来实现的)

  • TM 锁(表级锁)用于确保在修改表的内容时,表的结构不会改变,TM锁的种类有S,X,SR,SX,SRX五种,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。如下图所示

  • TX 锁(事务锁或行级锁)事务发起第一个修改时会得到TX锁(事务锁),而且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。TX锁用作一种排队机制,使得其他会话可以等待这个事务执行。事务中修改或通过SELECT FOR UPDATE 选择的每一行都会 指向 该事务的一个相关TX锁。

在数据行上只有X锁(排他锁),就是说TX锁只能是排他锁;

务 ID 存储在包含数据的块中,另一个会话到来时查看持有这个锁的事务是否还是活动 的。如果锁不活动,则允许会话访问这个数据。如果锁还是活动的,会话就会要求一旦释放锁就得到通知。因此,这就有了一个排队机制:请求锁的会话会排队,等待目前拥有锁的事务执行,然后得到数据。

DDL 锁(DDL lock): dictionary locks 字典锁,用来保护对象结构定义,如table,index的定义

在 DDL 操作中会自动为对象加 DDL 锁( DDL Lock ),在 DDL 语句执行期间会一直持有 DDL 锁,一旦操作执行就立即释放 DDL 锁。

  • 排他DDL 锁( Exclusive DDL lock ):这会防止其他会话得到它们自己的 DDL 锁或 TM ( DML )锁。这说明,在 DDL 操作期间你可以查询一个表,但是无法以任何方式修改这个表。
  • 共享DDL 锁( Share DDL lock ):这些锁会保护所引用对象的结构,使之不会被其他会话修改,但是允许修改数据。
  • 可中断解析锁( Breakable parse locks ):这些锁允许一个对象(如共享池中缓存的一个查询计划)向另外某个对象注册其依赖性。如果在被依赖的对象上执行 DDL , Oracle 会查看已经对该对象注册了依赖性的对象列表,并使这些对象无效。因此,这些锁是 可中断的,它 们不能防止 DDL 出现。


内部锁和闩:用来保护其内部数据结构,闩( l atch )是 Oracle 采用的一种轻量级的低级串行化设备,功能上类似于锁。轻量级指的是闩的实现,而不是闩的作用。

  • a:共享锁(share locks)  也称读锁,s锁 加了共享锁的数据对象可以被其他事务读取,但不能修改
  • b:排它锁 (exclusive locks) 也称写锁,x锁 当数据对象被加上排它锁时,其他的事务不能对它读取和修改

数据库利用这两种基本的锁类型来对数据库的事务进行并发控制

视图名

描述

主要字段说明

v$session

查询会话的信息和锁的信息。

sid,serial#:表示会话信息。
Program:表示会话的应用程序信息。
Row_wait_obj#:表示等待的对象。和dba_objects中的object_id相对应。

v$session_wait

查询等待的会话信息。

sid:表示持有锁的会话信息。
Seconds_in_wait:表示等待持续的时间信息
Event:表示会话等待的事件。

v$lock

列出系统中的所有的锁。

Sid:表示持有锁的会话信息。
Type:表示锁的类型。值包括TM和TX等。
ID1:表示锁的对象标识。
Lmode,request:表示会话等待的锁模式的信息。用数字0-6表示

dba_locks

对v$lock的格式化视图。

Session_id:和v$lock中的Sid对应。
Lock_type:和v$lock中的type对应。
Lock_ID1: 和v$lock中的ID1对应。
Mode_held,mode_requested:和v$lock中的lmode,request相对应。

v$locked_object

只包含DML的锁信息,包括回滚段和会话信息。

Xidusn,xidslot,xidsqn:表示回滚段信息。和v$transaction相关联。
Object_id:表示被锁对象标识。
Session_id:表示持有锁的会话信息。
Locked_mode:表示会话等待的锁模式的信息,和v$lock中的lmode一致。

QQ截图20120401160639.jpg

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21162451/viewspace-720176/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-06-07

  • 博文量
    30
  • 访问量
    203886