NuoDB
by NuoDB

MVCC. 方面的隔离级别:第1部分

好消息忠诚读者,徒步旅行是再次潜入Nuodb的事务语义。 Huzzah!特别是,我想指导这个博客的读者的关注,以传统的SQL隔离级别的含义 MVCC. 。有些人可能想知道孤立级别是什么。它是SQL标准的捕火角之一,因此我将开始快速审查为什么和唯一的隔离级别。

隔离级别:快速和脏概述

数据库事务语义通常用方便的首字母缩略词:酸。并且完全的事务系统应表现出原子性,一致性,隔离和耐用性。但是,所有这些属性都有成本。有时,应用程序开发人员希望放宽某些A,C和I属性,如果意味着性能的增加或简化应用程序。一个例子是具有一些逻辑的应用程序,谁是更新一些统计数据。在这种情况下,假设您需要更新全局累加器,以便客户端测量延迟,并为客户端的计数器凸起。这一切都可以为每个交易的全吹快照隔离进行,但它们会相互干扰。由于添加是固有的换向,所应用程序开发人员知道这两个操作不需要始终对“完全”的可见版本进行操作。它们可以针对“最新”版本进行。这应该允许2项交易来更新计数器而不会导致事务中止。在“经典”SQL中,有4个指定的隔离级别。它们是升值升值的顺序:READ_UNCOMMITED,READ_COMMITED,REPEALABLE_READ,SERIALIZABLE。查看 这里 对于深入概述。

如果您遵循该链接,或者熟悉标准的隔离级别的定义,则可能会记住它没有提及版本或可见性。这是因为标准的定义是基于锁的数据库。实际上,这些隔离级别中的每一个的写行为在锁定模式(共享与禁用)和持续时间方面定义。这对MVCC数据库的开发人员非常令人困惑,因为NOODB等MVCC数据库,因为MVCC的整个点是消除对显式表/行锁定的需求。但不要担心令人沮丧的开发人员,这博客帖子的其余部分专用于描述MVCC术语中的这些隔离级别。然后提供有用的例子!

NOODB的隔离级别

NOODB是分布式MVCC数据库。因此,对读异常和锁定持续时间的讨论不是描述隔离级别语义的直接方式。从MVCC的角度来看,需要在可见性方面描述一切。从Nuodb的角度来看,有两个可见域。一个是记录最新的致密版本(我会调用这个most_recent),另一个是在某个时间点最近提交的记录版本(我会调用此Snapshot_version)。

most_recent. 任何行的可见性是由已提交的事务安装的该行的最新版本。由于Nuodb是分布式系统,因此将通过负责承诺事务负责的节点通知一个节点。因此,有一种时间偏斜可能是可能的,其中一些节点将解释给定的交易,如提出,而其他节点(尚未接收和处理的提交消息)会将其解释为当前活动。这意味着大多数版本在调用中都不稳定,因为在远程节点上执行的事务可能从活动转换到版本计算之间的提交状态。

snapshot_version. 可见性完全稳定。启动事务时,已经提交的所有事务集确定了一组可见记录(用于整个交易持续时间)。这意味着在快照隔离下,事务将永远不会看到从一个调用到下一个调用的选择更改返回的一组行(除非该事务本身已更新从中选择的表格的内容)。结果是,可以获得更新冲突,其中快照隔离中的两个事务正在尝试更新相同的行版本。并且,解决此类冲突的唯一方法可能是回滚一个冲突的事务(以'重置'其快照)。

隔离级别MVCC语义

下表总结了其MVCC行为的隔离级别Nuodb支持。我们在Nuodb的Undersea Geodesic Dome Lair,已经选择呼叫快照隔离一致,但它是经典的快照隔离。 NOODB不完全支持重复的_Read,因为快照隔离比重复的重复更强(重复允许幻象读取,快照隔离阻止它们)。

隔离级别可见性规则
隔离级别 版本通过SELECT读取 由更新编写的版本
read_commited. most_recent. most_recent.
Adantent_read. 快照 快照
write_commited. 快照 most_recent.

 

 


 

read_commited. 与许多NoSQL产品相似。它始终返回最新版本。对于不关心全球读数的交易或正在进行严格的换向或幂等操作的交易,Read_Commited提供了最小的隔离程度。具有较少严格的一致性要求的应用程序可能能够正确地运行READ_COMMITED模式,并比AT AT AT AtteNt_Read实现更高的吞吐量。

Adantent_read. 是好的OL'快照隔离。这可以说是分布式数据库最明智的隔离级别,因为它完全绝缘在其他节点上的非冲突写行为的交易。 NB:在NOODB中,如果指定Serializable,则此隔离级别也是您获得的(在MVCC数据库中的不寻常)。虽然快照隔离不是标准隔离级别,但是许多数据库都支持它。实际上,使用MVCC的每个DB都能够进行快照隔离。它比重复_read更强烈,但不像全球序列化一样严格。

write_commited. 是诺福德的隔离级别。它旨在用于读取应该稳定的情况,但可以针对最新的承诺版本正确执行更新。统计信息更新事务的示例将是可以从write_commited中受益的事务的示例。

例1:读取

以下示例将使这些可见性规则更具体。对于这些示例,假设以下初始状态:

SQL> create table t1 (f1 integer);
SQL> insert into t1 values (1), (3), (5), (7), (9);
SQL> select * from t1;
 F1  
 --- 
  1  
  3  
  5  
  7  
  9  

这里的重要点是Read_Commited中的事务将能够读取最新的提交版本,因此在此示例中,它在事务1提交后看到插入的值2。具有快照读取可见性的这些事务将不会看到选择输出中的任何更改。重要的是要记住,在其他交易可见之前,交易1必须提交。 NOODB不允许所谓的脏读数。这是一件好事。

示例2:冲突更新

当2事务的写入集重叠时,此示例将说明隔离级别的差异。

read_commited / write_commited: 这里,事务2检测到的事务1的更新并阻止等待事务的最终状态1.当事务1承诺时,事务2根据最近的提交版本评估更新谓词,因为T不再是记录W f1 = 3,交易2的更新未更新任何行。

Accleant_read / Snapshot隔离: 更新导致事务2中的更新冲突2.因为T对事务2没有一致的方式选择记录版本并更新记录版本而无需Clobbering Transaction 1的更新。更新将失败,客户必须决定下一步该做什么。

示例3:非重叠写入

此示例将说明当写入集不重叠时的写行为,但写入全部针对同一表。

这种情况说明了一致_read和其他隔离级别之间的主要区别。在Adantuent_Read中,由于更新仅共享常见的行,因此在不协调的情况下可以进行两个事务。使用READ_COMMITED和WRITE_COMMITED,因为要更新的版本取决于最新的提交值,任何表更新都将强制延迟到达事务(事务2)必须阻止,直到更新事务(事务1)完成。如果更新程序提交,则其他事务将使用更新的行版本。如果更新事务中止,则其他事务必须使用前一行版本。在更新事务完成之前,无法执行此选择行版本。

包起来

隔离级别是一个复杂的主题。一方面,他们都是为了让用户放宽系统的一致性属性来挤出一些性能,并且完全一致 一件好事。另一方面,它们允许足够能力的开发人员显着提高DB应用的性能。它们是标准的一部分,所以Nuodb支持它们。从上面的示例中,我希望实际隔离级别的含义相当明确。我希望也很清楚,没有切割和干燥的配方来选择隔离级别。通常,Adantent_read(快照)隔离是完全安全的,可能是大多数应用的理想选择。如果事务不会一直更新相同的行,则ConsiveDent_Read通常是最执行的选项,因为它不需要在不属于更新集的行上阻止。但是,如果对某些共享行有很多写入争用,则READ_COMMITTED或WRITE_COMMITED可能是最佳选择。我希望你发现这个博客文章有用和信息。保持调整以获取更多信息,特别是与错误处理和更新延迟相关。

阅读本系列中的第二部分