`
linsea
  • 浏览: 90511 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Oracle 锁(1)

阅读更多

6.1           什么是锁?

锁(lock)机制用于管理对共享资源的并发访问。

首先,所有数据库本质上都不同。其次,学习每一个新数据库时,应该假设自己从未使用过数据库。在一个数据库中能做的事情在另一个数据库中可能没有必要做,或者根本不能做。

 

Oracle中,你会了解到:

l         事务是每个数据库的核心,它们是“好东西”。

l         应该延迟到适当的时刻才提交。不要太快提交,以避免对系统带来压力。这是因为,如果事务很长或很大,一般不会对系统有压力。相应的原则是:在必要时才提交,但是此前不要提交。事务的大小只应该根据业务逻辑来定。

l         只要需要,就应该尽可能长时间地保持对数据所加的锁。这些锁是你能利用的工具,而不是让你退避三舍的东西。锁不是稀有资源。恰恰相反,只要需要,你就应该长期地保持数据上的锁。锁可能并不稀少,而且它们可以防止其他会话修改信息。

l         Oracle中,行级锁没有相关的开销,根本没有。不论你是有1个行锁,还是1 000 000个行锁,专用于锁定这个信息的“资源”数都是一样的。当然,与修改1行相比,修改1 000 000行要做的工作肯定多得多,但是对1 000 000行锁定所需的资源数与对1行锁定所需的资源数完全相同,这是一个固定的常量。

l         不要以为锁升级“对系统更好”(例如,使用表锁而不是行锁)。在Oracle中,锁升级(lock escalate)对系统没有任何好处,不会节省任何资源。也许有时会使用表锁,如批处理中,此时你很清楚会更新整个表,而且不希望其他会话锁定表中的行。但是使用表锁绝对不是为了避免分配行锁,想以此来方便系统。

l         可以同时得到并发性和一致性。每次你都能快速而准确地得到数据。数据读取器不会被数据写入器阻塞。数据写入器也不会被数据读取器阻塞。这是Oracle与大多数其他关系数据库之间的根本区别之一。

 

6.2   锁定问题

6.2.1  丢失更新

6.2.2  悲观锁定

悲观锁定(pessimistic locking)仅用于有状态(stateful)或有连接(connected)环境,也就是说,你的应用与数据库有一条连续的连接,而且至少在事务生存期中只有你一个人使用这条连接。除了简单地查询值并验证数据尚未修改外,我们要使用FOR UPDATE NOWAIT锁定这一行。

 

6.2.3 乐观锁定

第二种方法称为乐观锁定(optimistic locking),即把所有锁定都延迟到即将执行更新之前才做。

1. 使用版本列的乐观锁定

这是一个简单的实现,如果你想保护数据库表不出现丢失更新问题,应对每个要保护的表增加一列。这一列一般是 NUMBER DATE/TIMESTAMP 列,通常通过表上的一个行触发器来维护。每次修改行时,这个触发器要负责递增 NUMBER 列中的值,或者更新DATE/TIMESTAMP列。

2. 使用校验和的乐观锁定

这与前面的版本列方法很相似,不过在此要使用基数据本身来计算一个“虚拟的”版本列。

3. 使用  ORA_ROWSCN 的乐观锁定

Oracle  10g  Release 1开始,你还可以使用内置的 ORA_ROWSCN 函数。它的工作与前面所述的版本列技术很相似,但是可以由Oracle自动执行,而不需要在表中增加额外的列,也不需要额外的更新/维护代码来更新这个值。除非你创建表时支持在行级维护ORA_ROWSCN,否则Oracle会在块级维护。也就是说,默认情况下,一个块上的多行会共享相同的 ORA_ROWSCN 值。如果更新一个块上的某一行,而且这个块上还有另外50行,那么这些行的ORA_ROWSCN也会推进。这往往会导致许多假警报,你认为某一行已经修改,但实际上它并没有改动。如果要在行级上维护则需要在建表时加上ROWDEPENDENCIES子句。

    另外可以把SCN转换为墙上时钟,但有一些限制:数据库的正常运行时间只有5天左右。如:select scn_to_timestamp(ora_rowscn) from dept;

6.2.4 乐观锁定还是悲观锁定?

 

6.2.5 阻塞

如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking)。这样一来,请求的会话会被阻塞,它会“挂起”,直至持有锁的会话放弃锁定的资源。几乎在所有情况下,阻塞都是可以避免的。实际上,如果你真的发现会话在一个交互式应用中被阻塞,就说明很有可能同时存在着另一个 bug,即丢失更新,只不过你可能没有意识到这一点。也就是说,你的应用逻辑有问题,这才是阻塞的根源。

数据库中有5条常见的DML语句可能会阻塞,具体是:INSERTUPDATEDELETEMERGESELECT FOR UPDATE

 

1. 阻塞的 INSERT

最常见的情况是,你有一个带主键的表,或者表上有惟一的约束,但有两个会话试图用同样的值插入一行。

一种解决方法是:创建一个触发器,在插入前,把插入行的主键散列到一个数字上,然后用一个排他锁把这个数字锁住,这样另一个人在插入相同的行时得不到这个锁,而收到一个错误,从而得知正试图插入相同行。

最后,还要记住,尽管Oracle有无限多个行级锁,但是 enqueue锁(这是一种队列锁)的个数则是有限的。如果在会话中插入大量行,而没有提交,可能就会发现创建了太

多的 enqueue 队列锁,而耗尽了系统的队列资源(超出了 ENQUEUE_RESOURCES 系统参数设置的最大值),因为每行都会创建另一个enqueue锁。如果确实发生了这种情况,就需要增大ENQUEUE_RESOURCES参数的值。还可以向触发器增加一个标志,允许打开或关闭这种检查。例如,如果我准备插入数百条或数千条记录,可能就不希望启用这个检查。

问题:什么是enqueue锁?为什么插入时每行都会创建另一个enqueue锁?ENQUEUE_RESOURCES 系统参数是个什么参数?

 

2. 阻塞的 MergeUpdate Delete

在一个交互式应用中,可以从数据库查询某个数据,允许最终用户处理这个数据,再把它“放回”到数据库中,此时如果 UPDATE DELETE阻塞,就说明你的代码中可能存在一个丢失更新问题(如果真是这样,按我的说法,就是你的代码中存在bug) 。你试图UPDATE

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

l         验证自从你查询数据之后数据未被修改(防止丢失更新)。

l         锁住行(防止UPDATEDELETE被阻塞)。

 

6.2.6 死锁

根据我的经验,导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新,这个内容将在第 11 章讨论)。

在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁:

l         如果更新了父表的主键(倘若遵循关系数据库的原则,即主键应当是不可变的,这种情况就很少见),由于外键上没有索引,所以子表会被锁住。

l         如果删除了父表中的一行,整个子表也会被锁住(由于外键上没有索引)。

 

在以下情况下,未加索引的外键也可能带来问题:

l         如果有ON DELETE CASCADE,而且没有对子表加索引:例如,EMPDEPT的子表,DELETE DEPTNO = 10应该CASCADE(级联)至 EMP[4]。如果 EMP中的 DEPTNO没有索引,那么删除 DEPT 表中的每一行时都会对 EMP 做一个全表扫描。这个全表扫描可能是不必要的,而且如果从父表删除多行,父表中每删除一行就要扫描一次子表。

l         从父表查询子表:再次考虑 EMP/DEPT 例子。利用 DEPTNO 查询 EMP 表是相当常见的。如果频繁地运行以下查询(例如,生成一个报告) ,你会发现没有索引会使查询速度变慢:

select * from dept, emp where emp.deptno = dept.deptno and dept.deptno = :X;

那么,什么时候不需要对外键加索引呢?答案是,一般来说,当满足以下条件时不需要加索引:

l         没有从父表删除行。

l         没有更新父表的惟一键/主键值(当心工具有时会无意地更新主键!)。

l         没有从父表联结子表(如DEPT联结到EMP)。

如果满足上述全部 3 个条件,那你完全可以跳过索引,不需要对外键加索引。如果满足以上的某个条件,就要当心加索引的后果。这是一种少有的情况,即Oracle“过分地锁定了”数据。

 

6.2.7 锁升级

如果数据库认为锁是一种稀有资源,而且想避免锁的开销,这些数据库中就会频繁使用锁升级。如果数据库支持锁升级,就说明这个数据库的锁定机制中存在某些内部开销,而且管理数百个锁需要做大量的工作。在Oracle中,1个锁的开销与1 000 000个锁是一样的,都没有开销。

注意:Oracle不会升级锁,从来不会。但是它会执行锁转换(lock conversion)或锁提升(lock promotion) ,这些词通常会与锁升级混淆。“锁转换”和“锁提升”是同义词。Oracle一般称这个过程为“锁转换”。

Oracle会尽可能地在最低级别锁定(也就是说,限制最少的锁),如果必要,会把这个锁转换为一个更受限的级别。

 

分享到:
评论

相关推荐

    Oracle的锁表与解锁

    ### Oracle的锁表与解锁:深入理解与操作 在Oracle数据库管理中,锁是一个至关重要的概念,用于控制多个用户或进程对数据的并发访问,确保数据的一致性和完整性。锁可以分为行级锁(Row Level Lock)和表级锁...

    oracle锁机制探讨

    表1:Oracle的TM锁模式 锁模式 锁描述 解释 SQL操作 0 none 1 NULL 空 Select 2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for update、Lock for update、Lock row share 3 SX(Row-X) 行级排它锁,...

    oracle锁表处理

    Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作,那么这些操作是怎么实现的呢?

    oracle解锁,死锁

    在深入讨论Oracle解锁和死锁之前,我们首先需要了解Oracle数据库中的锁机制。 1. **共享锁(S)**:允许多个用户读取行,但不允许修改。 2. **排他锁(X)**:允许单个用户修改行,其他用户只能等待。 3. **共享更新锁...

    oracle 锁的概念

    ### Oracle锁的概念与分类 #### 一、锁的基本概念 在Oracle数据库中,锁是一种用于管理并发事务的重要机制。通过锁机制,Oracle能够确保多用户环境下的数据一致性和完整性。简单来说,锁是为了防止多个用户同时...

    oracle解锁语句.txt

    oracle解锁语句,常用解锁语句,经过测试实用;oracle解锁语句,常用解锁语句,经过测试实用。

    Oracle 锁机制问题详解

    ### Oracle 锁机制问题详解 #### 一、引言 在多用户数据库环境中,当多个用户尝试同时访问或修改同一份数据时,就需要通过锁机制来确保数据的一致性和完整性。Oracle 数据库提供了多种类型的锁来支持事务隔离级别,...

    oracle存储过程解锁

    ### 描述:“如果存储过程被锁住,可以使用这个存储过程解锁方法” #### 解析: 当遇到存储过程被锁定的情况时,通常可以通过查询`dba_ddl_locks`视图来查找锁定的详细信息。例如,要检查名为`prc_exec_day`的存储...

    oracle锁表及解锁

    ### Oracle锁表与解锁详解 在Oracle数据库管理中,锁是一种关键机制,用于控制多个用户对数据资源的并发访问,防止数据冲突和不一致。本文将深入探讨Oracle中检查锁表的方法以及如何对表进行解锁。 #### Oracle锁...

    Oracle数据库的锁类型

    ### Oracle数据库的锁类型详解 #### 一、引言 Oracle数据库作为企业级数据库解决方案的佼佼者,其锁机制是保障数据完整性和并发控制的关键技术之一。在Oracle数据库中,锁的使用是为了协调多个用户对同一数据资源...

    oracle锁表和解锁语句示例.sql

    oracle锁表和解锁语句示例。

    oracle锁表查询oracle锁表查询oracle锁表查询

    ### Oracle锁表查询详解 #### 一、Oracle锁机制简介 在Oracle数据库中,锁是一种重要的并发控制机制,用于管理多个用户对同一数据资源的访问。通过锁机制,Oracle能够确保数据的一致性和完整性,避免多用户操作时...

    查看Oracle锁表

    ### 查看Oracle锁表 在Oracle数据库管理过程中,锁定机制是一项重要的功能,它用于确保数据的一致性和事务处理的安全性。当多个用户试图同时访问同一数据时,可能会出现并发问题,这时就需要通过锁定来控制对数据的...

    Oracle锁和表分区

    Oracle数据库系统中,锁和表分区是两个关键的管理数据并发和优化性能的机制。首先,我们来深入了解锁的概念。 1. **锁定机制**:锁定是数据库管理系统中用于控制并发访问的一种方法,确保多用户环境下的数据完整性...

    oracle锁库解锁方法

    针对oracle数据库 解锁方法 ,个人使用 希望大家能够有所帮助

    Oracle锁 图例

    本文将深入探讨Oracle锁的类型、工作原理以及相关的管理工具。 一、Oracle锁的类型 1. 表级锁:Oracle中的表级锁主要有两种,即排他锁(Exclusive Locks, X locks)和共享锁(Shared Locks, S locks)。排他锁允许...

    oracle锁表后,如何解锁

    Oracle锁表后如何解锁 Oracle锁表是指在Oracle数据库中某个表被锁定,无法进行操作的情况。这种情况经常发生在多用户同时访问同一个表时,某个用户锁定了该表,导致其他用户无法访问该表。那么,在不知道谁锁的情况...

Global site tag (gtag.js) - Google Analytics