Oracle 数据库允许多用户并发访问数据库,那么实现并发访问、控制和数据修改成为了一个重要问题,一方面它通过锁定机制实现数据库的并发控制,另一方面通过多版本模型来进行并发数据访问。
Oracle 的锁机制
锁模式
Oracle 在多用户数据库中使用两种模式的锁:
排他锁 | 阻止相关资源被共享。修改数据自动获得这个锁模式。如果排他锁没有释放,排他锁定一个资源的第一个事务是仅有的一个可以修改该资源的事务。 |
共享锁 | 允许相关资源被共享(和涉及的操作有关)。多个用户读取数据可以共享数据、持有共享锁来阻止并发的写入权限(需要排他锁)。多个事务可以在同一个资源上获得共享锁。 |
锁类型
Oracle 锁通常分为 3 类。
DML 锁(数据锁) | DML 锁保护数据。例如,表锁锁定整个表,行锁锁定选择行 |
DDL 锁(字典锁) | DDL 锁保护模式对象的结构,例如表和视图的定义 |
内部锁和闩 | 内部锁和闩保护内部数据库结构,比如数据文件。内部锁和闩是完全自动的 |
Oracle 自动使用不同类型的锁来控制数据的并发访问,阻止用户之间的破坏性干扰。 Oracle 自动为事务锁定一个资源,阻止其他需要同一资源的共享锁的事务获得锁。在某些条件下,事务不再需要资源时, Oracle 自动释放锁。
在这个操作中, Oracle 自动根据资源锁定情况和执行的操作在不同的限制级别上获得不同类型的锁。
DML 锁
DML 锁(数据锁)的目的是确保多个用户并发访问的数据的完整性。 DML 锁阻止了同时发生的冲突的 DML 或者 DDL 操作造成的破坏性干扰。 DML 语句自动获得行级锁和表级锁。
行锁( TX )
行级锁主要用于阻止两个事务同时修改一行。当事务需要修改一行时,需要获得一个行级锁。一个事务通过下列语句修改的每行都会获得一个行级互斥锁: INSERT 、 UPDATE 、 DELETE 和 SELECT ... FOR UPDATE 。行修改总是排他锁,所以其他的事务无法修改这一行,除非持有锁的事务提交或者回滚了。
如果一个事务在一行上获得一个行锁,事务也在对应表上获得一个表锁。这个表锁阻止了冲突的 DDL 操作,这个 DDL 操作可能覆盖当前事务中的数据修改。
表锁( TM )
表级锁主要用于并发控制并发的 DDL 操作,比如阻止在一个 DML 操作过程中删除相关表。当在一个表上执行 DDL 或 DML 语句,就获得一个表锁。一个事务在一个表使用下列 DML 语句: INSERT 、 UPDATE 、 DELETE 、 SELECT....FOR UPDATE 和 LOCK TABLE 时获得一个表锁。这些 DML 操作获得表锁有两个目的:为事务保留表的 DML 访问权限和阻止和这个事务冲突的 DDL 操作。任何表锁都阻止了同一个表上的排他 DDL 锁的获得,从而阻止了需要这个锁的 DDL 操作。
表锁可以以多种方式持有:行共享( row share , RS )、行排他( row exclusive , RX )、共享行排他( share row exclusive , SRX )、和排他锁( exclusive , X )。一个表的锁模式的限制确定了同一表上可以获得和持有的其他表锁。
语句获得表锁模式和这表锁允许和禁止的操作
SQL 语句 | 表锁模式 | 是否允许下列锁类型 | |||
RS | RX | SRX | X | ||
SELECT ..... FROM table | None | Y | Y | Y | Y |
INSERT INTO table .... | RX | Y | Y | N | N |
UPDATE table .... | RX | Y* | Y* | N | N |
DELETE FROM table ..... | RX | Y* | Y* | N | N |
SELECT .... FROM table FOR UPDATE OF ... | RS | Y* | Y* | Y* | N |
RS :行共享锁
RX :行排他锁
SRX :共享行排他锁
X :排他锁
* :如果没有其他事务持有冲突的行锁就为是,否则发生等待。
DML 语句获得的锁
DML 语句 | 行锁 (TX) | 表锁 (TM) |
SELECT ..... FROM table | None | None |
INSERT INTO table .... | X | RX |
UPDATE table .... | X | RX |
DELETE FROM table ..... | X | RX |
SELECT .... FROM table FOR UPDATE OF ... | X | RS |
DDL 锁
正在执行的 DDL 操作引用和操作的模式对象使用数据字典锁( DDL )来保护。前面说过, DDL 语句隐式的提交当前事务。例如,假定用户创建一个过程。对于用户的单语句进程来说, Oracle 自动对过程定义的所有引用的模式对象获得 DDL 锁。 DDL 锁阻止了过程编译完成之前其中的引用对象被修改结构或者删除的操作。