3.1 酸的出现

缩写词 ACID于 1983 年首次出现在 Theo Haerder 和 Andreas Reuter 的一篇文章中。为了简化文字并使其更具说服力,我将对本文的一个片段进行翻译(略有删减)。此代码段使用银行交易示例,其中资金从一个帐户转移到另一个帐户。

事务的概念,在示例中包括$BEGIN_TRANSACTION和之间与数据库的所有交互$COMMIT_TRANSACTION,要求所有操作不可分割地执行:要么所有操作都正确反映在数据库状态中,要么什么都不发生。$COMMIT_TRANSACTION如果在到达用户之前的任何时间点输入ERROR包含 的语句$RESTORE_TRANSACTION,则数据库中不会反映任何更改。

为了实现这种不可分割性,交易必须具有以下四个属性:

原子性(Atomicity)。交易必须是上述的all-or-nothing类型,无论发生什么,用户都必须知道交易处于什么状态。

一致性(Consistency)。达到其正常事务结束 (EOT) 并因此提交其结果的事务可维护数据库一致性。换句话说,每个成功的交易,根据定义,只提交有效的结果。这个条件是支持第四个属性——耐久性的必要条件。

隔离(隔离)。事务中发生的事件必须对其他并发执行的事务隐藏。如果不满足此条件,则由于上述原因,交易将无法返回到起点。为了实现隔离,使用称为同步的方法......

耐久性(Durability)。事务完成并将其结果提交到数据库后,系统必须确保这些结果在任何后续故障中仍然存在。由于不存在跨越事务集的控制范围,因此数据库管理系统 (DBMS) 无法控制超出事务边界的范围。

因此,必须保证用户,如果系统通知他发生了什么事,那么这个“事情”就真的发生了。由于,根据定义,任何(成功完成——S.K.)交易都是正确的,因此不可避免地出现错误交易(即包含错误数据的交易)的结果只能通过相应的“反”交易(countertransaction)来消除。

3.2 交易的出现

这四个属性——原子性、一致性、隔离性和持久性 (ACID)——描述了影响数据库系统设计许多方面的事务范式的核心特征。因此,我们认为,任何一个系统对交易的支持能力,都是这个系统好坏的试金石(ACID测试)。

将资金从一个帐户转移到另一个帐户的简单 PL/1-SQL 程序。

FUNDS_TRANSFER. PROCEDURE,
 $BEGIN_TRANSACTION;
 ON ERROR DO;                                   /* in case of error */
          $RESTORE_TRANSACTION,                 /* undo all work */
          GET INPUT MESSAGE;                    /* reacquire input */
          PUT MESSAGE ('TRANSFER FAILED');      /* report failure */
          GO TO COMMIT;
          END;
 GET INPUT MESSAGE;                             /* get and parse input */
 EXTRACT ACCOUNT_EBIT, ACCOUNT_CREDIT,
  AMOUNT FROM MESSAGE,
 $UPDATE ACCOUNTS                               /* do debit */
              SET BALANCE ffi BALANCE - AMOUNT
     WHERE ACCOUNTS.NUMBER = ACCOUNT_DEBIT;
 $UPDATE ACCOUNTS                               /* do credit */
              SET BALANCE = BALANCE + AMOUNT
     WHERE ACCOUNTS.NUMBER = ACCOUNT_CREDIT;
 $INSERT INTO HISTORY                           /* keep audit trail */
    <DATE, MESSAGE>;
 PUT MESSAGE ('TRANSFER DONE');                 /* report success */
COMMIT:                                         /* commit updates */
 $COMMIT_TRANSACTION;
 END;                                           /* end of program */

我提供了这段代码的示例来提醒您,实际上,ACID 属性一方面可以被视为任何声称支持事务的 DBMS 的要求,另一方面,作为事务的定义一个数据库系统。这个定义完全符合世俗惯例。例如,很难想象执行银行交易的客户(无论是在现场人工出纳员的帮助下还是使用网上银行)不期望银行满足 ACID 的所有属性。不支持其交易的 ACID 属性的银行充其量会失去客户,最坏的情况是破产。

3.3 酸连接

ACID 属性不可分割是非常重要的,丢弃其中任何一个都会使剩余的组合变得毫无意义。特别是,如果我们丢弃一致性属性(在上面引用中使用的意义上),那么我们将失去交易正确性的标准。数据库系统将无法以任何有意义的方式决定是否允许提交事务,并且必须在应用程序代码中执行对在数据库当前状态下执行的操作正确性的所有检查。

您需要了解,在这种情况下,我们谈论的是逻辑一致性。银行的客户需要银行按照他制定的并为客户所知的规则进行工作,这样就不可能执行任何违反这些规则的交易,从而使同一客户的下一次交易在一个环境同意按照这些规则。

在线商店的客户需要他订购并支付的商品及时交付给他(根据客户已知的既定规则)。否则,他不会信任这家店。同时,无论是银行的客户端还是网店的客户端,都不关心企业内部的厨房,内部采取了哪些动作来完成自己的交易。客户端不关心这个企业的物理一致性是如何维护的,物理层是如何操作的。

如果 DBMS 负责维护事务(和数据库)的逻辑一致性,那么应用程序将变得更简单、更易理解且更可靠。应用领域(银行、商店、仓库等)关于交易和数据有效状态的所有逻辑都进入数据库系统。而且这个系统的需求很简单:支持ACID事务,同时考虑到应用在数据库中提供的一致性规则。在我看来,拒绝 ACID 事务给应用程序开发人员带来了极大的困难,无论你喜欢与否,他们都必须自己实现类似的东西以满足客户的自然需求。

我再次注意到 ACID 属性实际上定义了事务的概念。在我看来,为了至少有可能讨论不支持事务一致性属性的事务数据管理系统,绝对有必要定义术语事务在这种情况下的含义。

不幸的是,今天在许多情况下(特别是,这是 NoSQL 方向的特征),人们在谈论支持 OLTP 应用程序时根本没有具体说明它们意味着什么类型的事务。因此,在本文中,我将使用组合 ACID 事务来指代真实的事务,而不限定术语事务在非正式意义上使用,在不同的上下文中有所不同。

现在让我们处理 CAP 的“定理”,并尝试弄清楚 Brewer 意义上的一致性意味着什么。