分布式 系列 并发控制

Posted by lichao modified on January 5, 2021

在数据库领域,并发控制是一个很具有挑战性的领域。常见的并发控制方式包括悲观并发控制、乐观并发控制和多版本并发控制

悲观并发控制

在关系数据库管理系统中,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,PCC)是一种并发控制的方法。它可以以影响其他用户的方式来阻止一个事务修改数据。如果一个事务执行的操作对某行数据应用了锁,那么只有在这个事务将锁释放之后,其他事务才能够执行与该锁冲突的操作。悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

乐观并发控制

乐观并发控制(又名“乐观锁”)也是一种并发控制的方法。它假设多用户并发的事务在处理时彼此之间不会互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务都会先检查在该事务读取数据之后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么正在提交的事务会进行回滚。

乐观并发控制多用于数据争用不大、冲突较少的环境,在这种环境中,偶尔回滚事务的成本会低于读取数据时锁定数据的成本,因此这种情况下乐观并发控制可以获得比其他并发控制方法更高的吞吐量。

多版本并发控制

多版本并发控制(Multiversion Concurrency Control, MVCC)并不是一个与乐观并发控制和悲观并发控制对立的概念,它能够与两者很好地结合以增加事务的并发量,目前最流行的 SQL 数据库 MySQL 和 PostgreSQL 都对 MVCC 进行了实现。MVCC 的每一个写操作都会创建一个新版本的数据,读操作会从有限多个版本的数据中挑选一个“最合适”(要么是最新版本,要么是指定版本)的结果直接返回。通过这种方式,读写操作之间的冲突就不再需要受到关注。因此,如何管理和高效地选取数据的版本就成了 MVCC 需要解决的主要问题。

多版本并发控制(Multi-Version Concurrency Control, MVCC)则以一种优雅的方式解决了锁带来的问题。在 MVCC 中,每当想要更改或者删除某个数据对时, DBMS 不会在原地删除或修改这个已有的数据对象本身,而是针对该数据对象创建一个新的版本,这样一来,并发的读取操作仍然可以读取老版本的数据,而写操作就可以同时进行。这个模式的好处在于,可以让读取操作不再阻塞,事实上根本就不需要锁。这是一种非常诱人的特性,以至于很多主流的数据库中都采用了MVCC 的实现,比如 MySQL 、PostgreSQL 、Oracle 和 Microsoft SQL Server 等。

多版本并发控制主要用于解决 读-写 的并发问题,并不能解决 写-写 的并发问题。总而言之, MVCC 能最大化地实现高效的读写并发,尤其是高效的读,因此其非常适合 “读多写少”的场景。