您的位置:首页 > 数据库

数据库锁定机制概述

2016-11-21 13:49 225 查看
锁是一种机制,用来防止多个共同访问共享数据的事务之间的破坏性交互,包括不正确地更新数据或不正确地更改基础数据结构锁在维护数据库并发性和一致性当中扮演着一个关键的角色

锁定行为总结

数据库维护几种不同类型的锁,这取决于获取锁的操作一般地,数据库使用两种类型的锁: 独占锁和共享锁在一个资源(如行或表)上,只能获得一个独占锁,但在单个资源上可以获得很多共享锁

锁会影响读取者与写入者的交互读取者是一个对某种资源的查询语句,而写入者是一个对某个资源的修改语句。以下规则总结了Oracle 数据库中读取者和写入者的锁定行为:

一行只有在被某个写入者修改时,才被锁定

当一个语句更新某行时,事务只需要获取在该行上的锁。通过在行级别锁定表数据,数据库最小化对同一数据的争用在正常情况下,数据库不会将行锁升级到块级或表级

一行的写入者,会阻塞在同一行上的并发写入者

如果一个事务正在修改某行,则行锁可防止不同的事务同时修改同一行。

一个读取者永远不会阻塞一个写入者

由于行的读取者不会将它锁定,所以一个写入者可以修改该行唯一的例外是SELECT … FOR UPDATE语句,它是一种特殊类型的SELECT语句,的确会锁定它正在读取的行

一个写入者绝不会阻塞一个读取者

当一个行正在被某个写入者更改时,数据库使用撤销数据向读取者提供一个该行的一致视图

注意:

在某些非常特殊的情况下,在挂起的分布式事务中,数据读取者可能需要等待相同数据块上的写入者。

使用锁

在单用户数据库中,锁不是必需的,因为只有一个用户在修改信息。但是,当多个用户在访问和修改数据时,数据库必须提供一种方法,以防止对同一数据进行并发修改。锁实现了以下重要的数据库需求:

 一致性

一个会话正在查看或更改的数据不能被其它会话更改,直到用户会话结束。

 完整性

数据和结构必须按正确的顺序反映对他们所做的所有更改。

Oracle 数据库通过其锁定机制,提供在多个事务之间的数据并发性、一致性、和完整性。锁定将自动执行,并且不需要用户操作

对锁的需求,可以由对某个单一行的并发更新来说明。在下面的示例中,一个简单的基于 web 的应用程序,将某个雇员的电子邮件和电话号码呈现给最终用户。应用程序使用如下所示的 UPDATE语句修改该数据:

UPDATE employees
SET email = ?, phone_number = ?
WHERE employee_id = ?
AND email = ?
AND phone_number = ?


在前面的 UPDATE语句中, WHERE子句中电子邮件和电话号码是某指定雇员的原始的、 未经修改的值。此更新可确保应用程序修改的行,在应用程序之前读取并向用户显示后,没有被更改过。以这种方式,应用程序可避免丢失更新的数据库问题,即其中一个用户覆盖了另一个用户所做的修改,实际上丢失了第二个用户所做的更新

表 9-4 显示两个会话在大致相同的时间,试图修改在雇员表中相同行的事件序列。











执行 SQL 语句时,Oracle 数据库自动获取所需的锁。例如,在数据库允许某个会话修改数据之前,该会话必须先锁定数据锁给予该会话对数据的独占控制权,以便在释放该锁之前,任何其他事务都不可以修改被锁定的数据

因为数据库的锁定机制与事务控制紧密地绑定在一起,应用程序设计人员只需要正确地定义事务,而数据库会自动管理锁定虽然数据库也支持用户能够手动锁定数据,但用户从来就不需要显式锁定任何资源

以下各节解释了理解数据库如何实现数据并发很重要的概念。

锁模式

Oracle 数据库自动使用最低适用的限制级别,来提供最高程度的数据并发,但还能提供非常安全的数据完整性限制级别越低、 则有更多的可用数据供其他用户访问。相反,限制级别越高,则其他事务为获取其所需的锁类型就将遭受更多的限制

Oracle 数据库在多用户数据库中使用两种锁定模式:

 独占锁模式(Exclusive lock mode)

此模式可防止相关资源被共享当一个事务修改数据时,获取一个独占锁。直到独占锁被释放之前,第一个以独占方式锁定资源的事务是唯一可以更改资源的事务

 共享锁模式(Share lock mode)

取决于所涉及的操作,此模式允许相关资源被共享读取数据的多个用户可以共享数据,并持有共享锁,以防止企图获取独占锁的写入者并发访问多个事务可以同时获取在同一资源上的共享锁

假定一个事务使用 SELECT … FOR UPDATE 语句选择一个单一表行。该事务获取一个独占行锁(exclusive row lock)和行共享表锁(row share table lock)。行锁允许其他会话修改除锁定行之外的任何行,而表锁可防止其它会话更改表结构。这样,数据库允许尽可能多的语句得以执行。

锁转换和锁升级

Oracle 数据库在必要时执行锁转换。在锁转换中,数据库自动将较低限制的表锁转换为较高限制的其它锁定

例如,假设事务对某雇员发出SELECT … FOR UPDATE,并之后更新了该锁定行。在这种情况下,数据库会自动将行共享表锁转换为行独占表锁(row exclusive table lock)。一个事务在该事务中所有执行插入、 更新、或删除的行上持有行独占锁。因为行锁是在最高程度限制下获得的,因此不要求锁转换,也不执行锁转换

锁转换不同于锁升级,锁升级发生在当某个粒度级别持有许多锁(例如行) ,数据库将其提高到更高粒度级别(例如表)。如果一个用户锁定了一个表中的许多行,则某些数据库自动将行锁升级到单个表锁。锁的数量减少了,但被锁定的东西却增加了

Oracle 数据库永远不会升级锁锁升级极大地增加了死锁的可能性。假定一个系统尝试升级事务 1中的锁,但因为事务 2持有该锁,故不能成功。如果事务 2在它可以继续操作之前也需要在相同的数据上进行锁升级,则将发生一个死锁。

锁持续时间

当某些事件发生,使事务不再需要资源时,Oracle 数据库会自动释放锁在大多数的情况下,数据库持有语句所获取的锁,直至该语句所在事务的整个持续期间结束这些锁可以防止破坏性干扰,如多个并发事务中的脏读、 更新丢失、和破坏性 DDL

注意:

因为未索引外键而在子表上发生的表锁,会在语句持续期间持有,而不是在事务持续期间。此外,DBMS_LOCK 包使得用户定义的锁可以按你的意志被释放或分配,甚至跨越事务边界而持有。

当Oracle 数据库提交或回滚事务时,会释放事务内的语句获取的所有锁当Oracle 数据库回滚至保存点时,也会释放该保存点之后所获取的锁但是,只有不在等待以前被锁定的资源的事务,可以获取现有可用资源上的锁等待中的事务会继续等待,直到原始事务提交或完全回滚

锁和死锁

死锁情况发生在两个或多个用户都在等待被对方锁定的数据时。死锁会阻止某些事务继续工作

Oracle 数据库自动检测死锁,并通过回滚死锁中的一个语句以释放其冲突行锁,来解决死锁。数据库向遭遇语句级回滚的事务返回一条相应的消息。被回滚语句属于检测到死锁的事务。通常,收到通知的事务应该明确回滚,但它可以等待一会之后重试被回滚的语句。

表 9-5 说明了在死锁中的两个事务。





当事务显式覆盖Oracle数据库的默认锁定时,最经常发生死锁。由于数据库不会升级锁,也不对查询使用读锁定,而是使用行级 (而不是页级别) 锁定,所以很少会出现死锁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: