数据库管理系统 (DBMS) 中使用锁的并发控制
锁是维护 DBMS 中并发控制的必要组成部分。在任何实现基于锁的并发控制的系统中,事务在获得所需锁之前,不能读取或写入语句。
基于锁的协议中有两种类型的锁:
- 二元锁 - 这些锁只有两种状态:锁定或解锁。
- 共享锁/排它锁 - 当只需要执行读取操作时,就获取共享锁。共享锁可以在多个事务之间共享,因为没有数据被更改。当执行写入操作时,使用排它锁。只有持有排它锁的事务才能更改数据值。
不同的锁协议包括:
简单的锁协议
事务在执行写操作之前,先获得对数据值的锁。写操作完成后,可以释放锁。简单的锁协议示例如下:
T1 | T2 |
---|---|
R(A) | |
R(A) | |
Lock(B) | |
R(B) | |
W(B) | |
Unlock(B) | |
Lock(C) | |
R(C) | |
W(C) | |
Unlock(C) | |
Commit | |
Commit |
上面显示了两个事务 T1 和 T2。读取操作不需要锁,但在写操作之前,每个事务都会获取一个锁,并在之后释放它。
两阶段锁协议
两阶段锁协议有两个阶段:增长阶段和收缩阶段。事务只有在增长阶段才能获取锁。当它进入收缩阶段时,它可以释放先前获取的锁,但不能获取新的锁。排它锁用 X 表示,共享锁用 S 表示。两阶段锁协议的示例如下:
T1 | T2 |
---|---|
S(A) | |
R(A) | |
S(A) | |
R(A) | |
X(B) | |
R(B) | |
W(B) | |
X(C) | |
R(C) | |
W(C) | |
Unlock(C) | |
Unlock(A) | |
Unlock(B) | |
Unlock(A) | |
Commit | |
Commit |
在上面的示例中,T1 和 T2 使用共享锁共享变量 A,因为只对 A 执行读取操作。T1 为写操作获取对 B 的排它锁,并在之后立即释放它。T2 对 C 也执行相同的操作。
严格的两阶段锁协议
严格的两阶段锁协议类似于两阶段锁协议。唯一的区别在于,在严格的 2PL 协议中,协议获取的所有排它锁都需要一直保持,直到协议提交或中止。严格的两阶段锁协议的示例如下:
T1 | T2 |
---|---|
S(A) | |
R(A) | |
S(A) | |
R(A) | |
X(B) | |
R(B) | |
W(B) | |
X(C) | |
R(C) | |
W(C) | |
Unlock(A) | |
Unlock(A) | |
Commit | |
Unlock(B) | |
Commit | |
Unlock(C) |
在上面的示例中,T1 和 T2 使用共享锁共享变量 A,因为只对 A 执行读取操作。T1 为写操作获取对 B 的排它锁,T2 对 C 也执行相同的操作。排它锁只有在事务提交后才能释放。但是,共享锁没有这样的限制。
严格两阶段锁协议
严格两阶段锁协议只是两阶段锁协议和严格两阶段锁协议的扩展。在这里,事务持有的所有锁,无论是共享锁还是排它锁,只有在事务提交或中止后才能释放。严格两阶段锁协议的示例如下:
T1 | T2 |
---|---|
S(A) | |
R(A) | |
S(A) | |
R(A) | |
X(B) | |
R(B) | |
W(B) | |
X(C) | |
R(C) | |
W(C) | |
Commit | |
Unlock(A) | |
Unlock(B) | |
Commit | |
Unlock(A) | |
Unlock(C) |
在上面的示例中,T1 和 T2 使用共享锁共享变量 A,因为只对 A 执行读取操作。T1 为写操作获取对 B 的排它锁,T2 对 C 也执行相同的操作。共享锁和排它锁只有在事务提交后才能释放。
广告