Jepsen发现PostgreSQL重大Bug:在单个PostgreSQL实例上以可串行化隔离执行的事务实际上是不可串行的


PostgreSQL是一个众所周知的关系数据库系统。我们使用Jepsen的新事务隔离检查器Elle评估了PostgreSQL ,发现在单个PostgreSQL实例上以可串行化serializability隔离执行的事务实际上是不可串行化的。
在正常操作下,事务有时可能会显示G2项:这是涉及一组事务的异常(大致而言),它们相互之间无法观察到彼此的写操作。
此外,我们在PostgreSQL“可重复读取”下发现了G2-item的频繁实例,这是由可重复读取的常见形式正式禁止的。正如Martin Kleppmann先前报道的那样,这是由于PostgreSQL的“可重复读取”实际上是快照隔离。
由于长期讨论ANSI SQL标准中的歧义,因此可以允许这种行为,但是对于熟悉该文献的用户来说,这可能是令人惊讶的。我们在8月13日发布了下一个次要版本的可串行化性错误修补程序,可通过文档轻松解决G2项在可重复读取下的存在。这项工作是独立进行的,没有任何补偿,并且是根据Jepsen道德政策执行的


建议
用户应注意,PostgreSQL的“可重复读取”实际上是快照隔离,这在PostgreSQL社区中早已为人所知,并且先前由Kleppmann报告。由于在可重复读取的常见形式化中禁止使用G2项,因此用户可能已经设计了应用程序,而这对于PostgreSQL而言是正确的。在这种情况下,用户可能希望改为在可串行化隔离下运行选定的事务,添加显式锁定或重新设计这些事务,以使它们不再对G2项敏感。
我们建议PostgreSQL团队更新其并发控制文档,以解决围绕“可重复读取”的歧义。在当前文档中没有提到的术语“快照隔离” -stating是PostgreSQL的“可重复读”,其实就是快照隔离会立即澄清事实。通过用G-single,G2-item和G2代替模棱两可的“串行化异常”,文档还可以为用户提供更清晰的指导;SI禁止使用单G,但允许G2和G2。
关于快照隔离是否比可重复读取强,一种可能的解决方案是采用Berenson等人的定义,这样做将使PostgreSQL与BerensonAdyaBailis等人在事务隔离方面的25年学术奖学金保持[url=https://www.vldb.org/pvldb/vol7/p181-bailis.pdf]一致[/url]。
似乎没有PostgreSQL版本可以保证可串行化。用户应注意,并发更新和插入事务可能会出现G2项目。高争用的工作负载尤其容易受到影响。PostgreSQL团队已经编写了测试来重现该问题,并正在评估补丁。我们建议在下一个次要版本可用时进行升级。


点击标题见原文详细分析。