二、锁
(一)
什么是锁
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
(二)锁的分类
根据保护的对象不同,
Oracle
数据库锁可以分为以下几大类:
DML
锁(
data locks
,数据锁),用于保护数据的完整性;
DDL
锁(
dictionary locks
,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(
internal locks and latches
),保护数据库的内部结构。
DML
锁的目的在于保证并发情况下的数据完整性,在
Oracle
数据库中,
DML
锁主要包括
TM
锁和
TX
锁,其中
TM
锁称为表级锁,
TX
锁称为事务锁或行级锁。
当
Oracle
执行
DML
语句时,系统自动在所要操作的表上申请
TM
类型的锁。当
TM
锁获得后,系统再自动申请
TX
类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查
TX
锁相容性时就不用再逐行检查锁标志,而只需检查
TM
锁模式的相容性即可,大大提高了系统的效率。
TM
锁包括了
SS
、
SX
、
S
、
X
等多种模式,在数据库中用
0
-
6
来表示。不同的
SQL
操作产生不同类型的
TM
锁。
在数据行上只有
X
锁(排他锁)。在
Oracle
数据库中,当一个事务首次发起一个
DML
语句时就获得一个
TX
锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行
DML
语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,
TX
锁被释放,其他会话才可以加锁。
(三)表级锁
行级排他锁(
Row Exclusive
,简称
RX
锁)
当我们进行
DML
时会自动在被更新的表上添加
RX
锁,或者也可以通过执行
lock
命令显式的在表上添加
RX
锁。在该锁定模式下,允许其他的事务通过
DML
语句修改相同表里的其他数据行,或通过
lock
命令对相同表添加
RX
锁定,但是不允许其他事务对相同的表添加排他锁(
X
锁)。
行级共享锁(
Row Shared
,简称
RS
锁)
通常是通过
select
…
from for update
语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出
rollback
命令将锁定解除。当表上添加了
RS
锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过
DML
语句或
lock
命令锁定相同表里的其他数据行。
共享锁(
Share
,简称
S
锁)
通过
lock table in share mode
命令添加该
S
锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出
select
…
from for update
命令对表添加
RS
锁。
排他锁(
Exclusive
,简称
X
锁)
通过
lock table in exclusive mode
命令添加
X
锁。在该锁定模式下,其他用户不能对表进行任何的
DML
和
DDL
操作,该表上只能进行查询。
共享行级排他锁(
Share Row Exclusive
,简称
SRX
锁)
通过
lock table in share row exclusive mode
命令添加
SRX
锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行
DML
操作,也不能添加共享锁。
这五种模式的
TM
锁的兼容关系如下表所示(
√表示互相兼容的请求;×表示互相不兼容的请求;
N/A
表示没有锁定请求):
- | S | X | RS | RX | SRX | N/A |
S | √ | × | √ | × | × | √ |
X | × | × | × | × | × | √ |
RS | √ | × | √ | √ | √ | √ |
RX | × | × | √ | √ | × | √ |
SRX | × | × | √ | × | × | √ |
N/A | √ | √ | √ | √ | √ | √ |
从前面的描述中可以看到,我们不仅可以通过发出
DML
语句的方式,由
Oracle
自动在表级别上添加
TM
锁。我们还可以通过发出
lock table
命令主动地在表级别上添加
TM
锁,并在该命令中可以指定不同的锁定模式,其命令格式如下所示:
lock table in [row share][row exclusive]
[share][share row exclusive][exclusive] mode;
对
Oracle
数据库中的各
SQL
语句所产生的表级锁的情况进行汇总,如下表所示:
SQL语句 | 表锁定模 | 允许的表锁定模式 |
Select * from …… | RS | RS、RX、S、SRX、X |
Insert into …… | RX | RS、RX |
Update …… | RX | RS、RX |
Delete from …… | RX | RS、RX |
Select * from for update | RS | RS、RX、S、SRX |
lock table in row share mode | RS | RS、RX、S、SRX |
lock table in row exclusive mode | RX | RS、RX |
lock table in share mode | S | RS、S |
lock table in share row exclusive mode | SRX | RS |
lock table in exclusive mode | X | RS |
对于通过
lock table
命令主动添加的锁定来说,如果要释放它们,只需要发出
rollback
命令即可。