不,我认为您的规定不会导致我们应该考虑可序列化的系统。
快照隔离是一种确保事务在整个事务中看到相同数据集的技术。快照隔离提供了一些保证,但并未定义理解事务真正工作所必需的所有特征(除非我们选择将快照隔离和MVCC混合使用)。
快照隔离最常使用MVCC(多版本一致性控制)来实现。MVCC在其快照的上下文中定义了事务的更多详细信息:据说它们仅在写入冲突时才需要隔离(仅位置,或位置+值,具体取决于实现)。MVCC提供了宽松的一致性模型,并且存在写偏斜的问题。
宽松的一致性模型很难理解,因为它们就像是没有隔离和完全隔离的混合体。
因此,让我们首先从严格的并发模型开始。如果一个事务写入另一个事务读取或写入的任何数据,则两个事务必须彼此隔离(反之亦然...)。
当我们不知道事务为何读取数据时,我们必须假定读取的其他值可能会改变所涉及的客户端的行为,这就是为什么事务重叠的情况表明隔离的原因。如果没有隔离,读取快照中的过时数据将很容易表现出宽松的一致性,这是术语不一致(也就是错误)。
我们只需要考虑交易读取或写入的确切数据,就不必考虑该集合以外的任何数据。但是,至关重要的是要意识到,当我们谈论事务读取的数据时,我们必须必须包含所有“元”数据(以及由元操作读取的数据和元数据,例如检查约束)。元数据的示例是/元操作是:唯一新主键的标识;另一个是整列的总和;另一种是寻找东西而不找到它;范围搜索或总和。这与@Matthew关于防止重复的评论以及@Tersosauros的答案有关,他认为状态是这样。
例如,这意味着两个事务都在插入一行时(假设唯一的主键约束)重叠(要求隔离),因为检查键约束与读取整个主键列同义。再举一个例子,搜索并找到它就像读取一个值,但是,找到它就像查看列中的每个值。
MVCC仅防止重叠或冲突的写入,但不防止读取(除非该事务也写入)。因此,要获得MVCC中的一致性错误,我们需要做的是读取由另一个事务更改的内容(其中另一个事务在获取前者的快照后发生,但首先提交),而另一个事务继续使用陈旧数据和与过时的数据相比,根据过时的数据做出的决策将有所不同。造成的后果比您想象的要容易。
宽松的一致性是表示潜在不一致或易于出错的另一种方式。(放松的一致性不应与最终的一致性混淆,后者是“ NoSQL”易于出错的另一种流行形式。)
在您的问题上,当您说事务不需要跨越一个以上的对象时,这必须同时适用于读取和写入以及元数据(和元操作),包括一致性检查,整列聚合,缺勤检查,范围搜索等。 。:如果是这样,那么到目前为止一切都很好。
然而...
我从您的问题中得知,您正在对单个对象使用快照隔离(MVCC)(例如,而不是对象锁定)。(您还提到了CAS;尽管我认为比较类似,但我听说过比较和交换,测试和设置,但没有检查和设置)。
您写的问题向我暗示“对象”具有多个字段,否则问题的规定将是不必要的。
因此,由于快照/ MVCC处理的对象具有多个字段,因此您倾向于在单个对象内写入歪斜。如果两个事务同时更新同一对象,则可能会读取同一对象上的并发其他事务使该对象的值过时的字段的值,然后继续进行操作而又不知道潜在的不一致(即错误)。
您可以改为使用对象锁定,这将防止两个事务(用于更新)甚至在正在处理同一事务的情况下也无法查看同一对象。
我相信无需使用MVCC损坏的仅写集比较模型就可以完成快照隔离的另一种形式。因此,您可以(从算法上)将比较集从只写方式提升为也包括读集。然后,两个更新同一对象的事务将无法引起写偏斜(因为稍后尝试提交的事务将被中止)。我认为这可能是解决您所描述问题的合适解决方案,因为通过排除多对象交易,您已经获得了MVCC可以为我们带来的大部分好处。
(我们只需要考虑读取或写入的确切和特定的项目/字段,但我们必须将这些读取的内容/字段包括为元数据,这可能在元操作期间进行,以防止出现写入偏斜(即错误)。如果我们从比较集中删除任一读取集, ,或者我们没有考虑元数据(可能由元操作使用),那么我们就有一个允许错误的模型。)