令人迷惑的CAP与ACID用语(二)

2015-07-24 08:53:30 · 作者: · 浏览: 5
列化属性,开发人员什么都不用做

然而,这是难以高效实现的,所以各数据库已经放松了限制。做为结果,数据库中的隔离性带有几个程度,即“可序列化(serializable)”, “可重复读(repeatable read)”, “读取已提交数据(read committed)”和“读取未提交数据(read uncommitted)”。

?

经常被默认使用的是“读取已提交数据”:一个事务只看到已经被(其它事务)提交的数据。

?

虽然看起来简单,但有几点隐情:

1. 正如Hellerstein、Stonebraker和Hamilton所说[D1] : “全以微妙的方式依赖于一个假设:有一个用于并发控制的锁机制,而不是一个乐观锁或多版本并发机制。这意味着提出的语义是不明确的。”

2. 对于一个给定的隔离度,所有的数据库不一定有相同的行为。这点由Martin Kleppmann解释于[D4]。

3. 隔离性不仅影响功能正确性,也影响技术正确性: 大多数据库在后台使用锁。并发执行时可能会产生死锁:独立事务间意料之外的或者不受控的依赖产生一种情况,所有事务均需其它事务释放占用的资源。 在这种情况下,其中一个事务会被数据库引擎终止并且失败, 即使这个事务其功能与语法都是正确的。

?

数据库用户需要了解的远远超过数据库一致性模型:他们需要了解他们所用数据库的引擎实际上如何实现它。

?

让我们再看下上面的那个例子。如果在“读已经提交数据”(通常是默认的)数据库上运行,我们可能会得到一个不正确的结果。我们实际上可能生成钱(多出钱来)。可通过显式锁定数据来修正,伪代码如下:

?

begin

val1 = readAndLock(account1)

val2 = readAndLock(account2)

newVal1 = val1 - 100

newVal2 = val2 + 100

write(account1, newVal1)

write(account2, newVal2)

commit // release all locks

?

随之到来的复杂性,已经在并发编程语言中遇到过,比如:Java。数据库实际上增加了一个额外的复杂度,就是锁的范围可以扩大(页、表、......),并能被数据库引擎动态调整(升级)。此外,死锁或者性能要求可能导致某些使用“读取未提交数据”隔离度,它假定读取的都是不可变数据。这也许会引出复杂问题,如果系统运行时,有人在某个地方(比如:客户网站上的专业服务专家)修改了理论上的不可变数据。

?

我们看到CAP的'C'与ACID的'I'十分相似。但CAP是应用到模型的一个理论,而性能限制迫使数据库中添加多个级别的参数,并迫使数据库用户了解隔离度如何实际执行。

?

结论

四个字母缩写的ACID,其中有3个有着与CAP中不同的含义,难怪这是令人迷惑的。而且,迷惑不仅来自于用语上的重叠, 也来自于探究实现细节去理解现实中并发应用上的不同。在实践中,这是导致许多人(包括我)看“NoSQL”世界的难点之一。

?

参考

[C2] Gilbert and Lynch. Brewer’s conjecture and the feasibility of consistent, available, partition-tolerant web services. ACM SIGACT News (2002)

[C6] Michael Stonebraker, Clarifications on the CAP Theorem and Data-Related Errors, 2010

[D1] J. M. Hellerstein, M. Stonebraker, J. Hamilton, Architecture of a Database System, Foundations and Trends in Databases Vol. 1, No. 2 (2007) 141–259

[D2] J. Gray and A. Reuter, Transaction Processing: Concepts and Techniques. Morgan Kaufmann, 1993.

[D4] M. Kleppmann, “Hermitage: Testing the “I” in ACID”, blog post, 2014

[V6] Nancy Lynch, Distributed Algorithms, Morgan Kaufmann, 1996

[V7] Kourosh Gharachorloo, “Memory Consistency Models for Shared-Memory Multiprocessors,” Stanford Technical Report, 1995

[V8] M. Herlihy, J. Wing “Linearizability: A Correctness Condition for Concurrent Objects”, ACM, 1990

[V9]Leslie Lamport, "How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs", IEEE Trans. Comput. C-28,9 (Sept. 1979), 690-691.