二阶段提交 2PL

二阶段提交

什么是 2PL

2PL(Two-Phase Locking),二阶段锁定,是数据库唯一广泛使用的一种可串行化算法

有时也称为严格两阶段锁定(SS2PL, strong strict two-phase locking),用来区分其他2PL的变体。

2PL 的特点是允许多个事务同时读取同一个对象,但对象只要有写入(修改或删除),就需要独占访问(exclusive access)的权限:

因此,在2PL中,写入会阻塞其他写入,也会阻塞读,反之,读也会阻塞其他写入。2PL提供了可串行化的性质,可以防止我们之前在[[2023-03-03-database-transactions]]提到过的所有竞争条件。

2PL用于 MySQL (InnoDB)和 SqlServer 中的可串行化隔离级别。

2PL 的具体实现

读与写的阻塞是通过为数据库中每个对象添加锁来实现的。锁可以处于 共享模式(shared mode)独占模式(exclusive mode)

谓词锁

谓词锁属于所有符合搜索条件的对象,即使数据库目前还不存在该对象。例如:

select * from bookings
where room_id = 123 and 
	end_time > '2018-01-01 12:00' and 
	start_time < '2018-01-01 13:00';

谓词锁的限制:

这里的关键思想是,谓词锁甚至适用于数据库中尚不存在,但将来可能会添加的对象(幻象)。如果两阶段锁定包含谓词锁,则数据库将阻止所有形式的异相,因此其隔离实现了可串行化。

索引范围锁

谓词锁性能不佳:如果活跃事务持有很多锁,检查匹配的锁会非常耗时,大多数数据库在实际中是使用索引范围锁(index-range locking,也称为 next-key locking),这是一个简化的近似版谓词锁,通过锁定比谓词锁更大的范围来近似模拟谓词锁。这种方式也能实现谓词锁的功能,并且开销更低,是一个很好的折衷。

如果没有可以挂载范围锁的索引,数据库可以退化到使用整个表上的共享锁。这是一个安全的回退策略。

参考

本文参考了如下文章: