一个数据库是否能支持“原子性”但不支持“一致性”,或者反之亦然?

27

我正在阅读关于数据库的ACID属性。原子性和一致性似乎密切相关。我在想是否有任何情况需要仅支持原子性而不支持一致性,或者反之亦然。一个例子会很有帮助!

我在了解数据库ACID属性。原子性和一致性紧密相关,通常都是一起实现的。但是,有时候在特定场景下我们可能只需要保证原子性而不需要保证一致性,或者相反。例如,在某些高并发的系统中,为了确保性能,我们可能会牺牲一致性。但这样做的代价是可能导致数据不一致的问题。因此,在选择支持原子性还是一致性时,需要根据具体业务需求进行权衡。
5个回答

31

它们有些相关,但存在微妙的差异。

原子性(Atomicity)意味着你的事务要么发生要么不发生。

一致性(Consistency)意味着执行诸如参照完整性之类的操作。

假设你开始一个事务来添加两行数据(信用和借记),这构成了一笔银行交易。这里的原子性和数据库的一致性无关。这只是表示要么两行都被添加,要么两行都没有被添加。

在一致性方面,假设你从订单(orders)产品(products)设置了外键约束。如果你尝试添加引用不存在的产品的订单,这时一致性就会防止你这样做。

它们都是为了维护数据库处于可运行的状态,因此它们很相似。前一个例子将确保银行不会损失钱财(或从你那里盗取它),后一个例子将确保你的应用程序不会因为你不知道的产品订单而感到惊讶。


11

原子性:

在原子事务中,一系列的数据库操作要么全部执行成功,要么全部不执行。原子性的保证可以防止仅部分更新数据库,这可能会导致比完全拒绝整个系列更严重的问题。

一致性:

在数据库系统中,一致性事务是指在其执行过程中不违反任何完整性约束条件。如果一个事务使得数据库处于非法状态,则会被中止并报告错误。

支持原子性但不支持一致性的数据库将允许产生处于不一致状态(即违反引用或其他完整性检查)的事务,只要该事务成功完成即可。例如,您可以向整数列添加字符串,前提是执行此操作的事务成功完成。

相反地,支持一致性但不支持原子性的数据库将允许部分事务完成,只要该事务的影响不会破坏任何完整性检查(例如,外键必须匹配现有标识符)。例如,你可以尝试添加包含字符串和整数值的新行,即使插入失败而丢失了一半的数据,只要未丢失数据是必需的列,未插入数据到类型不正确的列,该行就会被允许。

话虽如此,一致性依赖于原子性来撤消不一致的事务。


1
更正:事务在完成后不得使数据库处于违反约束条件的状态。然而,有些情况下,事务可能会暂时违反约束条件,但在完成之前解决了违规问题。 - Walter Mitty
谢谢Graphain和Walter! - rkg
@WalterMitty:支持原子性和一致性的数据库可以允许原子事务,其组成部分如果单独完成将使数据库处于不一致状态。我认为,不支持至少一些原子事务的数据库无法允许“临时不一致”。此外,虽然推迟强制执行约束直到“提交”肯定是有用的,但我不知道这种能力是否意味着特定数据库支持原子性和一致性;我认为Jet数据库可能是一个反例。 - supercat
一致性依赖于原子性来恢复不一致的事务。你能进一步解释一下吗? - Mehdi Charife

4
确实,原子性和一致性之间存在着很强的关系,但它们并不相同:
1. 理论上,DBMS可以支持一致性而不支持原子性:例如,考虑一个由SQL操作O1,O2和O3组成的事务。现在,假设在O1和O2之后,DB已经处于一致状态。那么DBMS可以在O1和O2之后停止事务而不执行O3,并仍然保持一致性。显然,这样的DBMS不支持原子性(因为O3未被O1和O2执行)。
2. 理论上,DBMS可以支持原子性而不支持一致性:这可能发生在多用户场景中,其中原子性仅确保将执行事务的所有操作(或其中任何一个),但不能保证与另一个事务同时进行的操作不会以不一致的状态结束。
然而,我相信(但尚未正式证明)的是,如果您的DMBS保证了原子性和隔离性,则它必须也保证一致性。

我也在考虑你在最后一句所说的那些。尚未得到证明,但似乎是合乎逻辑的。 - Avik Aggarwal

1
我在阅读有关原子性和一致性的内容时也感到困惑。假设有一个场景需要将1000条记录批量插入账户表。
如果所有1000条记录都被插入或者出现错误时没有任何记录被插入,则该批处理的原子性得到保证。
如果在账户记录级别上,我们已经设置了逻辑使插入成功,即使数据类型不匹配,在外键表中插入相关记录并在成功更新账户记录后删除,则该批次的一致性将受到破坏。
希望这个例子能够解决混淆。

0

我对 ACID 上下文中的一致性有不同的理解:

在一个事务中,如果检索了特定的数据项,并且在同一事务中稍后再次检索,那么不会看到任何更改。也就是说,在整个事务期间,数据库都处于一致的状态。唯一能够改变事务可见数据的更新只有事务本身进行的更新。

在我的理解中,这等同于可串行化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接