如果事务永远不会跨越多个对象,那么每个对象的乐观并发性是否意味着可串行化?


13

给定一个提供以下功能的系统:

  • 每个对象的乐观并发控制/版本控制(使用CAS-Check-and-Set)
  • 不需要跨多个对象的事务。
  • 快照隔离

该系统是否可序列化

快照隔离

在写偏斜异常中,两个事务(T1和T2)同时读取重叠的数据集(例如值V1和V2),并发进行不相交的更新(例如T1更新V1,T2更新V2),最后并发提交,都没有看到对方执行的更新。如果系统可序列化,那么这种异常将是不可能的,因为T1或T2都必须“首先”发生,而另一个则可见。相反,快照隔离允许写偏斜异常。

举一个具体的例子,假设V1和V2是一个人Phil持有的两个天平。银行将允许V1或V2出现赤字,前提是两者中所持的总和决不为负(即V1 + V2≥0)。目前两个余额均为$ 100。Phil同时发起了两个交易,T1从V1提取200美元,T2从V2提取200美元。

基于此,似乎存在写偏斜的可能性是保证快照隔离不可序列化的系统的唯一原因。

但是,在不允许事务跨越多个对象的系统中(在上面的示例V1和V2中),似乎不可能发生写偏斜

因此,上述系统是可序列化的。它是否正确?


1
我认为答案是肯定的,前提是允许数据库中止将导致写入时滞的事务-如果事务仅限于读/写单个对象,则它们是不相交或冲突的。
pjc50

2
我认为您还需要一些方法来防止首次提交重复记录。在这种情况下,两个乐观的作家可以看到每一个空的快照,该记录是新的,所以你可以在0.1版本有两个对象,每个对象
马修马克米勒

Answers:


1

不,我认为您的规定不会导致我们应该考虑可序列化的系统。

快照隔离是一种确保事务在整个事务中看到相同数据集的技术。快照隔离提供了一些保证,但并未定义理解事务真正工作所必需的所有特征(除非我们选择将快照隔离和MVCC混合使用)。

快照隔离最常使用MVCC(多版本一致性控制)来实现。MVCC在其快照的上下文中定义了事务的更多详细信息:据说它们仅在写入冲突时才需要隔离(仅位置,或位置+值,具体取决于实现)。MVCC提供了宽松的一致性模型,并且存在写偏斜的问题。

宽松的一致性模型很难理解,因为它们就像是没有隔离和完全隔离的混合体。

因此,让我们首先从严格的并发模型开始。如果一个事务写入另一个事务读取或写入的任何数据,则两个事务必须彼此隔离(反之亦然...)。

当我们不知道事务为何读取数据时,我们必须假定读取的其他值可能会改变所涉及的客户端的行为,这就是为什么事务重叠的情况表明隔离的原因。如果没有隔离,读取快照中的过时数据将很容易表现出宽松的一致性,这是术语不一致(也就是错误)。

我们只需要考虑交易读取或写入的确切数据,就不必考虑该集合以外的任何数据。但是,至关重要的是要意识到,当我们谈论事务读取的数据时,我们必须必须包含所有“元”数据(以及由元操作读取的数据和元数据,例如检查约束)。元数据的示例是/元操作是:唯一新主键的标识;另一个是整列的总和;另一种是寻找东西而不找到它;范围搜索或总和。这与@Matthew关于防止重复的评论以及@Tersosauros的答案有关,他认为状态是这样。

例如,这意味着两个事务都在插入一行时(假设唯一的主键约束)重叠(要求隔离),因为检查键约束与读取整个主键列同义。再举一个例子,搜索并找到它就像读取一个值,但是,找到它就像查看列中的每个值。

MVCC仅防止重叠或冲突的写入,但不防止读取(除非该事务也写入)。因此,要获得MVCC中的一致性错误,我们需要做的是读取由另一个事务更改的内容(其中另一个事务在获取前者的快照后发生,但首先提交),而另一个事务继续使用陈旧数据和与过时的数据相比,根据过时的数据做出的决策将有所不同。造成的后果比您想象的要容易。

宽松的一致性是表示潜在不一致或易于出错的另一种方式。(放松的一致性不应与最终的一致性混淆,后者是“ NoSQL”易于出错的另一种流行形式。)

在您的问题上,当您说事务不需要跨越一个以上的对象时,这必须同时适用于读取和写入以及元数据(和元操作),包括一致性检查,整列聚合,缺勤检查,范围搜索等。 。:如果是这样,那么到目前为止一切都很好。

然而...

我从您的问题中得知,您正在对单个对象使用快照隔离(MVCC)(例如,而不是对象锁定)。(您还提到了CAS;尽管我认为比较类似,但我听说过比较和交换,测试和设置,但没有检查和设置)。

您写的问题向我暗示“对象”具有多个字段,否则问题的规定将是不必要的。

因此,由于快照/ MVCC处理的对象具有多个字段,因此您倾向于在单个对象内写入歪斜。如果两个事务同时更新同一对象,则可能会读取同一对象上的并发其他事务使该对象的值过时的字段的值,然后继续进行操作而又不知道潜在的不一致(即错误)。

您可以改为使用对象锁定,这将防止两个事务(用于更新)甚至在正在处理同一事务的情况下也无法查看同一对象。

我相信无需使用MVCC损坏的仅写集比较模型就可以完成快照隔离的另一种形式。因此,您可以(从算法上)将比较集从只写方式提升为也包括读集。然后,两个更新同一对象的事务将无法引起写偏斜(因为稍后尝试提交的事务将被中止)。我认为这可能是解决您所描述问题的合适解决方案,因为通过排除多对象交易,您已经获得了MVCC可以为我们带来的大部分好处。

(我们只需要考虑读取或写入的确切和特定的项目/字段,但我们必须将这些读取的内容/字段包括为元数据,这可能在元操作期间进行,以防止出现写入偏斜(即错误)。如果我们从比较集中删除任一读取集, ,或者我们没有考虑元数据(可能由元操作使用),那么我们就有一个允许错误的模型。)


0

我认为,正如@ pjc50所说,(强调添加:)如果事务仅限于读/写单个对象”,那么“答案是肯定的”。但是,我认为这归结于单个对象的想法。

在从快照隔离中获取的示例中,T1和T2不共享任何值。但是,它们仍然存在写偏斜的可能性,因为“ 两个都没有看到另一个执行的更新 ” 。因此,它是能力事务的看到所有其他更新提交之前,使一个真正的交易序列化。

从可序列化性

计划的可序列化性是指在相同事务下,等效于串行计划(在结果上,数据库状态,数据值)与串行计划(即顺序的,时间上没有事务重叠)。

不幸的是,因此(正如@Matthew Mark Miller指出的那样),我们还必须考虑状态和价值。考虑到这一点,每当写入任何数据库状态时,使用OCC进行的两个事务都有写偏斜的可能性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.