DBMS 并发控制

2025 年 5 月 20 日 | 阅读 10 分钟

并发控制 (Concurrency Control) 是数据库中用于管理发生在数据库上的并发操作的管理程序。

但在了解并发控制之前,我们应该先了解并发执行。

DBMS 中的并发执行

  • 在多用户系统中,多个用户可以同时访问和使用同一个数据库,这称为数据库的并发执行。这意味着在多用户系统上,不同的用户同时执行同一个数据库。
  • 在处理数据库事务时,需要多个用户使用数据库来执行不同的操作,在这种情况下,就会进行数据库的并发执行。
  • 关键在于,同时执行应该以交错的方式进行,并且任何操作都不应影响其他正在执行的操作,从而保持数据库的一致性。因此,在进行事务操作的并发执行时,会产生一些需要解决的挑战性问题。
  • 例如:在像航空公司预订系统这样的大型计算机系统中,数据库会被多个用户共享。每个获得更新数据库权限的用户都使用事务进行操作。应用程序可以同时执行事务,因为每个用户都不知道其他用户的存在,因此这些并发事务可能会相互干扰,导致数据库不一致。
  • 解决此问题的一种可能方法是强制事务顺序执行,每个事务仅在前一个事务完成后才开始。顺序执行事务耗时很长。除了这个原因之外,还有其他两个原因要在此时间执行事务。
    • 一个事务由多个步骤组成。其中一些可能涉及输入/输出活动,而另一些可能执行 CPU 活动。这两种活动是相互独立的,可以并行执行。这允许多个事务并发运行。当一个事务正在执行读/写操作时,另一个事务可以被分配到 CPU。同样,其他事务在输入/输出操作和 CPU 操作之间切换。这个过程类似于多程序设计,结果是系统的吞吐量增加,即单位时间内事务的数量增加。这也会导致 CPU 利用率的提高。
    • 当多个事务并发执行时,其中一些可能是长时间事务,一些可能是短事务。如果这些事务被串行执行,短事务必须等待长时间事务完成,这会导致事务执行出现不可预测的延迟。因此,事务被设置为并发运行,执行事务。

并发执行的问题

在数据库事务中,两个主要操作是 **读取 (READ)** 和 **写入 (WRITE)** 操作。因此,在事务的并发执行中需要管理这两个操作,因为如果这两个操作没有以交错的方式执行,数据可能会变得不一致。因此,并发执行操作时会发生以下问题:

问题 1:丢失更新问题 (W - W 冲突)

当两个不同的数据库事务以交错的方式(即并发执行)对同一个数据库项执行读/写操作,导致项的值不正确,从而使数据库不一致时,就会发生此问题。

例如

考虑下面的图,其中两个事务 TX 和 TY 对同一个账户 A 执行操作,账户 A 的余额为 300 美元。

DBMS Concurrency Control
  • 在时间 t1,事务 TX 读取账户 A 的值,即 300 美元(仅读取)。
  • 在时间 t2,事务 TX 从账户 A 中扣除 50 美元,余额变为 250 美元(仅扣除,未更新/写入)。
  • 交替地,在时间 t3,事务 TY 读取账户 A 的值,仍然是 300 美元,因为 TX 尚未更新该值。
  • 在时间 t4,事务 TY 向账户 A 添加 100 美元,余额变为 400 美元(仅添加,未更新/写入)。
  • 在时间 t6,事务 TX 写入账户 A 的值,余额将仅更新为 250 美元,因为 TY 尚未更新该值。
  • 类似地,在时间 t7,事务 TY 写入账户 A 的值,它将写入时间 t4 完成的操作,即 400 美元。这意味着 TX 写入的值丢失了,即 250 美元丢失了。

因此,数据变得不正确,数据库设置为不一致。这是因为其中一个更新丢失了。此调度代表了多个事务并发执行的丢失更新问题。

因此,要克服这个问题,我们应该确保在给定时间内只有一个事务可以修改给定的数据项,并且其他事务即使在查看数据库中未修改的值时也应该被锁定,直到修改提交到数据库。

脏读问题 (W-R 冲突)

当一个事务更新了数据库的一个项,但该事务不幸失败,并且在数据回滚之前,更新后的数据库项被另一个事务访问时,就会发生脏读问题。这时,两个事务之间就发生了读-写冲突。

例如

考虑下面的图中的两个事务 TX 和 TY,它们在账户 A 上执行读/写操作,账户 A 的可用余额为 300 美元。

DBMS Concurrency Control
  • 在时间 t1,事务 TX 读取账户 A 的值,即 300 美元。
  • 在时间 t2,事务 TX 向账户 A 添加 50 美元,余额变为 350 美元。
  • 在时间 t3,事务 TX 将更新后的值写入账户 A,即 350 美元。
  • 然后,在时间 t4,事务 TY 读取账户 A,将读取到 350 美元。
  • 然后,在时间 t5,事务 TX 由于服务器问题而回滚,值会变回 300 美元(如初始值)。
  • 但对于事务 TY 来说,账户 A 的值仍然是提交的 350 美元,这就是脏读,因此被称为脏读问题。

不可重复读问题 (W-R 冲突)

到目前为止,我们已经讨论了丢失更新问题和脏读问题。这两个问题都与并发运行事务时数据库的更新有关。但是,当读取数据库中的数据项时,也可能出现问题,这类问题称为不可重复读。

也称为不一致检索问题,当事务中对同一个数据库项读取了两次(或多次)不同的值时发生。

当多个事务并发运行时,如果一个事务对同一个数据项进行了两次(或多次)读取,并且在两次读取(或多次读取)之间,另一个事务更新了该数据项,导致该事务在其对同一个数据项的两次读取中获得不同的值,就会发生不可重复读问题。

例如

考虑两个事务 TX 和 TY,它们对账户 A 执行读/写操作,可用余额为 300 美元。下图所示。

DBMS Concurrency Control
  • 在时间 t1,事务 TX 从账户 A 读取值,即 300 美元。
  • 在时间 t2,事务 TY 从账户 A 读取值,即 300 美元。
  • 在时间 t3,事务 TY 通过向可用余额添加 100 美元来更新账户 A 的值,然后变为 400 美元。
  • 在时间 t4,事务 TY 写入更新后的值,即 400 美元。
  • 之后,在时间 t5,事务 TX 读取账户 A 的可用值,将读取到 400 美元。
  • 这意味着在同一事务 TX 中,它读取了账户 A 的两个不同值,即最初的 300 美元,以及事务 TY 更新后读取的 400 美元。这是不可重复读,因此被称为不可重复读问题。

因此,为了保持数据库的一致性并避免并发执行中发生的问题,需要进行管理,而这正是并发控制概念发挥作用的地方。

在现实世界中,让我们考虑这样一个情况:银行员工运行一个事务,读取银行所有账户余额的总和。假设同时运行着其他事务,这些事务通过存款或取款来更新账户余额,那么第一个事务计算出的总数可能是错误的,因为它可能在更新之前读取了一些余额,而在更新之后读取了另一些余额。

并发控制

并发控制是用于控制和管理数据库操作的并发执行,从而避免数据库不一致的工作概念。因此,为了维护数据库的并发性,我们有并发控制协议。

为什么需要并发控制?

当并发执行不受控制时,可能会出现许多问题,因此我们需要对其进行控制。并发控制是管理数据库中的更新、删除等并发操作的活动,而不允许它们相互重叠。换句话说,并发控制致力于确保两个或多个用户不会互相干扰。

开发数据库的主要目的是允许许多并发用户访问数据库。开发 I/O 和 CPU 活动可以减少磁盘和处理器空闲时间,并提高系统吞吐量。只要所有访问数据库的用户只执行读取操作,并发访问就不会引起任何问题。当两个或多个并发用户访问数据库,其中一个尝试更新数据库时,可能会出现问题。在这种情况下,由于事务的干扰,可能会出现不一致。因此,有必要控制对数据库的并发访问,以避免出现任何不一致。

并发事务中的挑战

隔离是社区在支持并发事务的 DBMS 中实现数据一致性、完整性和良好性能时必须考虑的主要问题之一。以下是一些主要的困难:

数据一致性

丢失更新:当两个或多个事务尝试读取同一个记录、修改它然后写回时发生,这将导致只有一个更改被写入。

临时不一致:当一个事务正在读取另一个事务正在同时处理的数据时出现,导致中间值或不可预测的值。

数据完整性

不可重复读:当一个事务重试读取操作并获得与之前不同的值,因为另一个事务在此期间更新了该值时发生。

幻读:当一个事务重新提交一个返回满足某个条件的行集的查询,并发现该行集已被另一个插入或删除行的事务更改时发生。

隔离级别和性能

低隔离级别:例如,未提交读 (Read Uncommitted) 和已提交读 (Read Committed) 会使查询运行得更快,但同时也会带来脏读和不可重复读的可能性。

高隔离级别:因此,我们有可重复读 (Repeatable Read) 和串行化 (Serializable) 选项等技术,它们可以确保数据一致性,但会损害并发性和系统性能。

死锁

检测和解决:之后,为了识别 死锁,有必要监控正在进行的事务,这些事务涉及资源及其分配;这些的计算在计算上很密集,意味着解决死锁需要中止一个或多个事务;这对系统吞吐量和用户满意度有负面影响。

预防和避免:操作系统中解决或最小化死锁的策略或措施会降低并发性,从而导致资源利用不足。

资源争用

锁争用:如果有许多事务需要使用锁,则可能会出现小的原始事务速率,并且当事务速率很高时会出现长时间等待。

硬件资源限制:当有大量并发事务时,这会在有限数量的 CPU、内存和 I/O 操作上产生争用问题。

并发控制机制

锁的使用在 DBMS 并发控制中非常重要,因为它用于控制多个事务而不会对数据库进行不同步的更改。在这些协议中起重要作用的一些概念是共享锁和排他锁,以及两阶段锁定 (2PL) 和严格两阶段锁定。

并发控制协议

并发控制协议确保数据库事务并发执行的 **原子性 (atomicity)、一致性 (consistency)、隔离性 (isolation)、持久性 (durability)** 和 **可串行化性 (serializability)**。因此,这些协议被分类为:

  • 基于锁的并发控制协议
  • 时间戳并发控制协议
  • 验证式并发控制协议

我们将在接下来的部分逐一理解和讨论每个协议。

现在是一些重要的单选题

1. __________ 是操作的集合,它们共同构成了一个逻辑工作项。

  1. 网络
  2. 传输
  3. 沟通
  4. 交易
 

答案:d

解释:事务是操作的集合,它们共同构成了一个逻辑工作项。数据库系统必须正确地确保事务的完成。


2. _________ 是用于描述“全有或全无”特性的术语。

  1. 以上都不是
  2. 隔离
  3. 原子性
  4. 耐用性
 

答案:c

解释:原子性是用于描述“全有或全无”特性的术语。它保证没有中间步骤,任务要么完成,要么未完成。


3. 以下哪个选项描述了事务的属性?

  1. 提及的所有内容
  2. 原子性
  3. 隔离
  4. 耐用性
 

答案:d

解释:事务的三个特性是持久性、原子性和隔离性。


4. 两阶段锁定 (2PL) 协议的潜在缺点是什么?

  1. 它不能确保可串行化。
  2. 它可能导致死锁。
  3. 它允许脏读。
  4. 它阻止事务获取锁。
 

答案:b

解释:2PL 协议的主要缺陷是容易导致死锁,即两个或多个事务无限期地等待对方释放锁。


5. 与标准 2PL 相比,严格两阶段锁定 (Strict 2PL) 的一个关键优势是什么?

  1. 提高并发性
  2. 防止级联中止
  3. 消除死锁
  4. 降低锁定开销
 

答案:b

解释:Strict 2PL 在事务提交或中止之前会一直持有所有锁,阻止其他事务看到中间的、未提交的状态,从而防止了级联中止。