在有关事务隔离级别的PostgreSQL文档中,我们可以阅读以下内容:
虽然在主服务器上执行可序列化事务中的所有永久数据库写入将确保所有标准最终达到一致状态,但在备用上运行的可重复读取事务有时会看到与主服务器上可序列化事务的任何串行执行不一致的瞬态。 以上文本位于http://www.postgresql.org/docs/9.4/static/transaction-iso.html_的底部。
在什么情况下,在热备用上运行的可重复读取事务会出现不一致的瞬态?
发布于 2015-06-22 17:41:37
Geir的回答是正确的;我的回应只是提供一个例子和可能的解决办法,因为人们常常很难理解这个问题。除了在另一个答案中引用的Wiki页面之外,还有一个单独的Wiki页面仅供示例使用,它包括将批处理视为已关闭但还不能看到批处理的最终细节的“存款报告”的例子。
热备用是只读的,所以它只能看到短暂的序列化异常;数据最终会在一些后续事务中稳定到一致的状态。这与主服务器上的可重复读取事务相同,对于主服务器上可序列化的事务是不可能的。为了防止混乱,在热备用状态下不允许可序列化的事务,因为还不能保证在那里看到真正可序列化的事务行为。有人说要向WAL流添加信息,以确定可以在哪些点启动可序列化的事务,而不会出现异常,类似于DEFERRABLE选项的START TRANSACTION;这个(或类似的东西)可能会添加到未来的某个版本中。
对于使用快照隔离的只读事务(包括在甲骨文或9.1之前的PostgreSQL版本中可序列化的事务),最常见的异常类型似乎是选择列表或汇总一个批处理,该批处理在事务中显示为“已关闭”,而没有看到批处理中应该包含的所有工作。要查看这一点,关闭批处理的事务必须“重叠”(与某些修改批处理详细信息的事务同时运行),关闭批处理的事务必须首先提交,然后(在事务结束批处理提交之后,在修改批处理详细信息提交事务之前)只读事务必须启动并获取其快照。
为了防止这种情况,最简单的技术是从读-写依赖关系到写-写冲突,在主数据上“促进冲突”。例如,在上面引用的“存款报告”示例中,可以向控制表中添加一个deposit_total列,当deposit_no增加时,该表被设置为零,并且可以向收据表中添加一个AFTER触发器,以根据每个收据的数量更新金额。这将导致基于控件记录的写入冲突的序列化失败,从而防止异常传播到副本。
发布于 2015-03-03 16:36:38
看起来,这可能发生在批处理和类似的应用程序。
我在一个关于SSI的wiki页面中找到了一些关于这个主题的信息,以及postgresql黑客邮件列表中的一些背景细节,他们在该列表中讨论了如何在热站上处理序列化。
Kevin在他的帖子中写道: 在我看来,发生这种情况的最常见和令人震惊的情况是批量处理。这在金融应用中是非常普遍的,而且在很多其他地方也会出现。 。。 但是,待机上的查询在运行查询时会看到瞬态异常,如果在事务流的同一位置在主服务器上运行,则会导致序列化失败。只有在两个并发事务中,一个似乎第二次运行,因为另一个无法读取它所写的内容,才会发生这种情况。 。。 在SSI下,其中一个事务将被取消,以防止出现这种情况。我们的实现将始终允许关闭批处理的更新完成,并且根据这些事务中操作的时间安排,插入或选择详细信息都将以序列化失败的方式回滚。如果插入失败,则可以重试,并将进入新批处理--使该批处理的列表没有问题。如果取消了批处理详细信息的列表,这将是因为在它识别问题之前提交到旧批处理中的插入,因此立即重试select将看到完整的批处理内容。 热备用不能真正参与主服务器上的谓词锁定和事务取消。
https://stackoverflow.com/questions/28833623
复制相似问题