数据库锁定机制概述
2016-11-21 13:49
225 查看
锁是一种机制,用来防止多个共同访问共享数据的事务之间的破坏性交互,包括不正确地更新数据或不正确地更改基础数据结构。锁在维护数据库并发性和一致性当中扮演着一个关键的角色。
锁定行为总结
数据库维护几种不同类型的锁,这取决于获取锁的操作。一般地,数据库使用两种类型的锁: 独占锁和共享锁。在一个资源(如行或表)上,只能获得一个独占锁,但在单个资源上可以获得很多共享锁。
锁会影响读取者与写入者的交互。读取者是一个对某种资源的查询语句,而写入者是一个对某个资源的修改语句。以下规则总结了Oracle 数据库中读取者和写入者的锁定行为:
一行只有在被某个写入者修改时,才被锁定。
当一个语句更新某行时,事务只需要获取在该行上的锁。通过在行级别锁定表数据,数据库最小化对同一数据的争用。在正常情况下,数据库不会将行锁升级到块级或表级。
一行的写入者,会阻塞在同一行上的并发写入者。
如果一个事务正在修改某行,则行锁可防止不同的事务同时修改同一行。
一个读取者永远不会阻塞一个写入者。
由于行的读取者不会将它锁定,所以一个写入者可以修改该行。唯一的例外是SELECT … FOR UPDATE语句,它是一种特殊类型的SELECT语句,的确会锁定它正在读取的行。
一个写入者绝不会阻塞一个读取者。
当一个行正在被某个写入者更改时,数据库使用撤销数据向读取者提供一个该行的一致视图。
注意:
在某些非常特殊的情况下,在挂起的分布式事务中,数据读取者可能需要等待相同数据块上的写入者。
使用锁
在单用户数据库中,锁不是必需的,因为只有一个用户在修改信息。但是,当多个用户在访问和修改数据时,数据库必须提供一种方法,以防止对同一数据进行并发修改。锁实现了以下重要的数据库需求:
一致性
一个会话正在查看或更改的数据不能被其它会话更改,直到用户会话结束。
完整性
数据和结构必须按正确的顺序反映对他们所做的所有更改。
Oracle 数据库通过其锁定机制,提供在多个事务之间的数据并发性、一致性、和完整性。锁定将自动执行,并且不需要用户操作。
对锁的需求,可以由对某个单一行的并发更新来说明。在下面的示例中,一个简单的基于 web 的应用程序,将某个雇员的电子邮件和电话号码呈现给最终用户。应用程序使用如下所示的 UPDATE语句修改该数据:
在前面的 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数据库的默认锁定时,最经常发生死锁。由于数据库不会升级锁,也不对查询使用读锁定,而是使用行级 (而不是页级别) 锁定,所以很少会出现死锁。
锁定行为总结
数据库维护几种不同类型的锁,这取决于获取锁的操作。一般地,数据库使用两种类型的锁: 独占锁和共享锁。在一个资源(如行或表)上,只能获得一个独占锁,但在单个资源上可以获得很多共享锁。
锁会影响读取者与写入者的交互。读取者是一个对某种资源的查询语句,而写入者是一个对某个资源的修改语句。以下规则总结了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数据库的默认锁定时,最经常发生死锁。由于数据库不会升级锁,也不对查询使用读锁定,而是使用行级 (而不是页级别) 锁定,所以很少会出现死锁。
相关文章推荐
- SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
- SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
- Teradata 数据库技术概略之二 —— 数据分布机制(1) 概述
- 第 7 章 MySQL 数据库锁定机制
- MySQL 数据库锁定机制
- 读《MySQL性能调优与架构设计》笔记之MySQL 数据库锁定机制
- SQL SERVER的锁机制(二)——概述(锁的兼容性与可以锁定的资源)
- 第 7 章 MySQL 数据库锁定机制
- Teradata 数据库技术概略之二 —— 数据分布机制(1) 概述
- MySQL 性能优化篇 (七) 数据库锁定机制
- 数据库锁机制(一)——概述
- oracle 数据库中的锁机制研究
- .NET中的反射机制概述
- 数据库概述
- Oracle中的数据锁定机制
- Oracle数据库数据锁定机制全面解析
- 开放源码的嵌入式数据库Berkeley DB 概述
- Linux数据库系统MySQL应用概述
- 数据库的数据挖掘概述
- 使用数据库的机制来确保数据的正确性