1 锁的作用
在数据库服务器允许会话修改数据之前,会话必须首先锁定被修改的数据。锁给予会话对数据独占控制,以便在锁被释放之前,其他事务都不能修改被锁定的数据。
事务可以锁定数据的单独行、多行,甚至整个表。Oracle数据库同时支持手动和自动锁定。对于自动获取的锁,选择尽可能低的锁定级别,以最小化与其他事务的潜在冲突。
注意:Oracle服务器使用许多类型的锁来维护内部一致性。
2 锁机制
锁定机制旨在提供数据库中最大程度的数据并发性。修改数据的事务获取行级锁,而不是块级或表级锁。对对象的修改(如表移动)获得对象级锁,而不是整个数据库或模式锁。
数据查询不需要锁,即使有人锁定了数据,查询也会成功(总是显示根据undo信息重新构建的原始预锁值)。
当多个事务需要锁定同一资源时,第一个请求锁定的事务获得该资源。其他事务一直等到第一个事务完成。队列机制是自动的,不需要与管理员交互。
在事务完成时(即发出提交或回滚时)释放所有锁。在事务失败的情况下,自动回滚失败事务的任何更改的同一后台进程释放该事务持有的所有锁。
3 细粒度
锁定机制默认的细粒度为行级锁定模式。不同的事务可以更新同一表中的不同行,而不会相互干扰。
虽然默认的模型是在行级别锁定,但如果需要,Oracle数据库支持在更高级别手动锁定:
SQL> LOCK TABLE employees IN EXCLUSIVE MODE;
表锁定。
对于上述语句,试图更新被锁表中的行的任何其他事务都必须等待,直到发出锁请求的事务完成。EXCLUSIVE是最严格的锁模式。以下是其他的锁模式:
ROW SHARE:允许并发访问被锁定的表,但是禁止会话锁定整个表进行独占访问
ROW EXCLUSIVE:与行共享相同,但也禁止在共享模式下锁定。行独占锁在更新、插入或删除数据时自动获得。行独占锁允许多个读取和一个写入。
SHARE:允许并发查询,但禁止对已锁表的更新。为了在表上创建索引,需要(并自动请求)共享锁。但是,在线创建索引需要在构建索引时使用的行共享锁。
共享锁允许多个读取而不允许写入。当删除或更新父表中的行时,共享锁也会透明地使用,因为父表中的子表具有外键约束。
SHARE ROW EXCLUSIVE:用于查询整个表,并允许其他人查询表中的行,但禁止其他人以共享模式锁定表或更新行
EXCLUSIVE:允许对被锁定的表进行查询,但禁止在其上进行任何其他活动。删除表需要使用排他锁。
与任何对锁的请求一样,手动锁语句会等待,直到所有已经拥有锁或之前请求过锁的会话释放它们的锁。LOCK命令接受一个控制等待行为的特殊参数NOWAIT。
如果指定的表已经被另一个会话锁定,NOWAIT立即返回控制给你:
SQL> LOCK TABLE hr.employees IN SHARE MODE NOWAIT;
LOCK TABLE hr.employees IN SHARE MODE NOWAIT
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
通常没有必要手动锁定对象。自动锁定机制提供了大多数应用程序所需的数据并发性。Oracle建议避免使用手动锁,特别是在开发应用程序时。不必要的高锁级别常常导致严重的性一级标题能问题。
4 DML锁
每个DML事务获得两个锁:
正在更新的行上的排他行锁
正在更新的表上的行排他(RX)模式的表锁™。这可以防止另一个会话在进行更改时锁定整个表(可能会删除或截断它)。这种模式也称为子异常表锁(SX)。
表上的行排他锁防止DDL命令在未提交事务的中间更改字典元数据。这样可以在事务的整个生命周期中保持字典完整性和读取一致性。
5 锁的排队机制
对锁的请求会自动排队。一旦持有锁的事务完成,下一个会话就会收到锁。
入队机制跟踪请求锁的顺序和所请求的锁模式。
已经持有锁的会话可以请求转换锁,而不必到达队列的末尾。例如,假设会话持有一个表上的共享锁。会话可以请求将共享锁转换为排他锁。如果表上没有其他事务已经拥有排他或共享锁,那么持有共享锁的会话将被授予排他锁,而不必再次在队列中等待。
注意:排队的等待者有两种类型:没有共享所有权的等待者和没有选择升级锁级别的共享所有权的等待者。第二类的等待器称为转换器,即使它们等待的时间更短,它们也总是比普通的等待器具有优先级。




