乐观并发控制和写入偏差

3
我感到有点蠢,不过为了澄清事情,有时候必须问一些蠢问题 :)
所以,我们可以像Martin Kleppmann在他的演讲中那样定义写偏斜:
写偏斜模式: 1. 读取某些内容 2. 做出决定 3. 写出决策 当写操作(3)提交时,决策(2)的前提(1)已不再成立
有一种悲观的方法,基本上是说“在给定的时刻只有一个主题可以使用共享资源,其他人应该等待主题完成”。
然后有一种乐观的方法,其中定义了维基百科中的阶段:
I. 开始:记录标记交易开始的时间戳。 II. 修改:读取数据库值,并暂时写入更改。 III. 验证:检查是否有其他事务修改了该事务使用的数据(包括读取或写入)。这包括在此事务开始时间之后完成的事务,以及可选地,在验证时间仍处于活动状态的事务。 IV. 提交/回滚:如果没有冲突,则使所有更改生效。如果存在冲突,则通过通常是放弃事务的方式解决它,尽管可能还有其他解决方案。
我的问题是,在进行验证(III)时,我们有什么保证新的“知识”不会被写入,从而实现了上述的写偏斜定义?
基本上,验证模块在第三阶段必须保留一些内部分类帐,并以串行方式处理它们,使得来自事务2的检查过程不会发生在事务1的写入事件之前。
我们只是将写偏斜问题下移一级吗?因此,我们在低层采用可串行悲观方法以便在更高层采用乐观方法?我理解对吗?
我很感激任何澄清。
1个回答

2
对于乐观锁来说,“III. 验证”和“IV. 提交/回滚”需要成为一个原子操作。因此,在这种意义上,“我们只是将写入偏斜的整个问题向下移了一级”。
然而,“II. 修改”是数据库控制之外的用户操作,可能需要很长时间才能完成,并且无法通过数据库实现进行优化。相反,“III. 验证”和“IV. 提交/回滚”是由数据库实现的操作,可以通过数据库实现进行快速优化。

我之所以提出这个问题,是因为在更高级别的“微服务+事件溯源”中,使用本地数据库+单线程会出现 OCC 问题,因此我们基本上将写偏斜问题转移到不同的级别?整个想法归结为“最终底部的某人需要按顺序和悲观方式进行处理”,对吧? - Twice_Twice
1
@Twice_Twice 对,除非可以完全避免冲突(例如使用CRDTs,但这是另一个故事)。但在可能发生冲突的更新面前,总会存在一定的互斥访问窗口。将此窗口尽可能缩小并不延伸到用户操作是OCC的目标。 - michid
1
非常感谢,现在我更深入地理解了这个主题! - Twice_Twice

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