最近我正在学习事务数据库中的并发控制技术。但是,我对操作系统和事务数据库中的并发控制之间的差异感到非常困惑。
在我的理解中,数据库文献中介绍的并发控制技术可以用于多线程程序,其线程之间共享一些变量,反之亦然。多线程程序中用于在线程之间共享变量的技术也可以在数据库中用于并发控制。
为什么我们要费心在数据库文献和操作系统中以不同的方式介绍这一点?
最近我正在学习事务数据库中的并发控制技术。但是,我对操作系统和事务数据库中的并发控制之间的差异感到非常困惑。
在我的理解中,数据库文献中介绍的并发控制技术可以用于多线程程序,其线程之间共享一些变量,反之亦然。多线程程序中用于在线程之间共享变量的技术也可以在数据库中用于并发控制。
为什么我们要费心在数据库文献和操作系统中以不同的方式介绍这一点?
数据库有两个并发要求。一种是对引用的内存块进行非常短期的物理管理。这些在 DB 世界中被称为锁存器,可以使用互斥锁等来实现。这里关注的是在工作线程访问内存块时的稳定性。
第二个控制数据库中保存的客户端数据的有效性和隔离性。它们控制对逻辑事物(元组、表等)而不是物理硬件相关事物(内存块)的访问。这些被称为锁。它们的持续时间与客户端事务的持续时间一样长,可以是任意长的时间。锁通常保持在与保持锁定对象的结构不同的结构中。因此,锁定的东西不需要在持有锁的整个持续时间内都在内存中。例如,可能会读入一个页面,插入一行并对其进行锁定以确保隔离。如果包含新行的页面被驱逐,锁将保持有效。确实,被锁的东西在被取锁的时候可能就不存在了!范围锁保护键值从下限到上限。获取锁时,这些值都不需要存在于数据中,也不能存在落在该范围内的值。尽管如此,锁将生效并允许隔离客户的工作。
Goetz Graefe 的“ B 树锁定技术概览”的介绍部分很好地涵盖了这些想法。
操作系统只处理其中的第一个(以我有限的专业知识)。任何磁盘扩展都隐藏在虚拟内存和页面文件后面。相比之下,DBMS 显式处理 RAM 和磁盘驻留以针对其特定用例进行优化。不同的需求导致 OS 和 DBMS 之间的处理方式不同。
除了 Michael Green 在他的出色回答中指出的内容之外,您还应该了解乐观并发,它是数据库中的一种应用程序级技术,用于防止两个用户(或进程)尝试修改同一部分数据的。当对单个数据进行两次更新的可能性很低但非零时使用该技术。至少从概念上讲,这是与竞态条件类似的场景,但它并不相同,并且不需要相同的处理,因此操作系统可能使用的技术不能以完全相同的方式应用于应用程序数据库。
该场景是两个用户,例如 Bob 和 Jane,读取数据库中的客户记录。他们都看到了相同版本的记录。然后 Bob 保存更改,假设该记录上的客户地址。稍晚一点,Jane 保存了一个不同的零钱,假设是客户的信用额度。由于 Jane 不知道 Bob 的更改,因此 Jane 的更改会覆盖 Bob 的更改,从而导致 Bob 的更改丢失。
在应用程序级别,您可以通过几种不同的方式来防止这种情况。一种是在保存更改之前重新读取所有数据,以确保自上次读取以来没有更改。如果记录有很多字段,这有点繁琐。第二种方法是使用每条记录中的单个字段作为标记,每次任何人保存对记录的更改时都会更新该标记。您可以使用诸如字段之类的东西来执行此操作
last_modified_datetime
,但根据记录更新的积极程度,这可能不够精确。许多 RDBMS 都有一个特性来帮助解决这个问题。例如,SQL Server 有一种称为ROWVERSION
(以前称为TIMESTAMP
)的数据类型,它是系统生成的二进制字段,每次更新记录时都会由数据库自动修改。为确保 Bob 没有突然闯入并修改 Jane 手下的数据,她会在
update
声明中包含以下内容:...WHERE CustomerID=@CustID AND CustRowVersion=@LastModRowVersion
(*)Jane 检查她的更新语句的受影响行数,如果数字为 0,她知道 Bob(即其他人)一直在使用他的老把戏,她需要刷新她的数据视图并重新应用她的更改。
为什么在应用程序级别使用乐观并发?您可以改为使用悲观并发,并且在 Bob 锁定记录时不让 Jane 读取记录。一些系统将以这种方式构建。问题是设计选择和用户要求之一。当发生冲突的机会小于两个人同时使用相同记录的机会时,使用乐观并发。例如,假设 Bob 只想读取(而不是更新)客户的地址。在那种情况下,为什么要锁定记录并阻止简做她的工作并修改客户的信用额度?
(*) 这些是糟糕的字段/变量名称,我不建议您使用这些糟糕的名称!
迈克尔·格林和乔尔·布朗给出了涵盖大部分内容的出色答案。让我加上我的两分钱。如果并发控制基本上是为了防止幻像更新,那么问题就出现了,与受保护的数据容器相关的粒度级别是什么。
对于操作系统而言,受幻像更新保护的用户数据归结为磁盘文件的块和用户内存的页面。操作系统本身内部管理着较小的数据单元,但这里的并发控制通常对用户社区是透明的。
一些操作系统在文件管理系统之上有一个分层的记录管理系统,这个记录管理系统可能对记录级别的数据有一些锁定控制。我无视这个功能。
DBMS 通常关注与操作系统完全不同的粒度级别的数据共享和并发控制。至少,DBMS 必须关注表行级别和索引节点级别的数据共享。许多 DBMS 的级别远不止于此。
此外,DBMS 用户使用 SET TRANSACTION、COMMIT 和 ROLLBACK 积极参与事务管理,以向 DBMS 指示事务边界。当用户在磁盘块级别共享文件时,许多操作系统没有任何用户级别的事务指示器。
如果没有 DBMS 的事务管理和并发控制功能,在共享数据库上运行的应用程序将面临执行瓶颈和不可重现的结果之间的不可接受的权衡。