什么是数据库事务的写偏斜write-skew?- justinjaffray


这篇文章是关于写歪斜write-skew的知识以及扩展快照隔离的知识。快照隔离被称为事务隔离级别,它在性能和正确性之间提供了很好的组合,但是此处“正确性”的确切含义通常含糊不清。在这篇文章中,我想分解并准确记录何时发生“写偏斜”事件。
 
事务快速入门
数据库中的执行单位是事务。事务是工作的集合,这些工作要么全部完成,要么根本不运行。没有半成品事务。通常围绕事务提供许多保证,但是我们将重点放在隔离上。隔离使数据库的用户不必担心并发性,它决定了事务显示的程度,好像它在数据库中单独运行一样。
各种可能的隔离级别的分类是一个有趣的话题,但是在这里,我们将只关注它们之间的关系:SERIALIZABLE和“ Anomaly SERIALIZABLE”(有时称为SNAPSHOT快照)。
 
可串行化SERIALIZABLE
从某种意义上说,可串行性是“完美”的隔离。似乎每个事务实际上都是完全在数据库中单独运行的,即使这可能这不是真正的幕后情况(我的服务器有很多内核,我们需要充分利用它们)。如果我们独自运行所有事务,则将其称为“串行化”。由于这等效于单独运行它们,因此称为可串行化。
串行执行是指我们一次只运行一次事务,而不会由于并发而交错操作。
我们可以将可串行化性视为一种方案,其中每个事务在一个唯一的时间戳上逻辑上完成其所有工作。由于每笔交易至少在概念上都是瞬时发生的,因此用户不必担心麻烦的并发性。
顺便说一句,值得注意的是“ SERIALIZABLE串行化隔离级别”和“可串行化的执行”是两个不同的概念。我所见过的大多数讨论都将它们混为一谈,尽管这会引起一些令人困惑的问题,例如“被表示为“可串行化”的事务如何与非串行化事务进行交互”?
 
异常串行化Anomaly SERIALIZABLE(快照)
可串行化性很奇怪,它是事务理论中为数不多的概念之一,具有非常简单和明确的定义,但仍以某种方式设法具有两种完全不同的主流含义。
过去,当ANSI定义SERIALIZABLE隔离级别时,它们的定义虽然正确,但可以解释为不排除较低的隔离级别(现在称为“快照隔离”),少数进取的数据库供应商利用了这一事实。最著名的例子是,如果您向Oracle请求SERIALIZABLE,实际上得到的是SNAPSHOT(快照)。
从某种意义上说,整篇文章都是关于了解快照隔离的处理方法。
快照隔离的主要特征有两个:

  • 快照隔离中的事务有两个重要的时间戳:一个是执行读操作的时间戳,另一个是执行写操作的时间戳。读取的时间戳定义了事务看到的数据库的“一致快照”。如果其他人在事务T的读取时间戳记之后的某个时间提交写操作,则将看不到这些更改(通常使用MVCC强制执行。我们将名为“ x”的事务称为T x,并将读取和写入时间戳记分别记为R x和W x。
  • 如果两个事务执行的间隔重叠(R 1 <W 2和W 1 > R 2),则两个事务并发。在“快照隔离”中,数据库强制两个并发的已提交事务具有不相交的写集(这意味着它们不会写到任何相同的内存位置)。提交将导致违反此限制的任何事务都将被迫中止并重试。

 
写偏斜
快照隔离中发生的异常称为“写入偏斜”。
其典型示例如下所示:
考虑两个事务P和Q。P将寄存器x中的值复制到y,Q将寄存器中的值从y复制到x。只有两个串行执行:P,Q或者Q,P。无论哪种方式,最终结果都是x = y。但是,快照隔离允许另一个结果:
  • 事务P读取x
  • 事务Q读取y
  • 事务P将其读取的值写入y
  • 事务Q将其读取的值写入x

这在“快照隔离”中是可以有效的发生:每个事务维护数据库的一致视图,并且其写集与任何并发事务的写集不重叠。但是其实x和y已被交换,这两种串行执行都无法实现结果。
 
更多点击标题见原文。
 
结论
如果您运行的是主流数据库,则您运行的隔离级别很可能是SNAPSHOT,甚至更低。几乎没有主流数据库默认为真正串行化SERIALIZABLE,许多根本没有提供它。考虑到SNAPSHOT的盛行,我认为了解确切含义很重要。
正如我希望您已经说服的那样,“写偏斜”这一公认的例子是不够的。如果您想了解更多有关此主题的信息,那么我不能说太多:

感谢Arjun Narayan,Ben Darnell,Sean Loiselle,Ilia Chtcherbakov和Forte Shinko阅读此帖子并提供反馈。