Fly*_*yer 5 postgresql transactions transaction-isolation database-replication
在有关事务隔离级别的PostgreSQL文档中,我们可以阅读以下内容:
在主服务器上的Serializable事务中执行所有永久数据库写入时,将确保所有备用数据库最终都将达到一致状态,在备用数据库上运行的可重复读取事务有时会看到一个与序列化事务的任何串行执行不一致的瞬态.主.
以上文字位于http://www.postgresql.org/docs/9.4/static/transaction-iso.html的底部
在什么情况下,在热备份上运行的可重复读取事务可能会看到不一致的瞬态?
Geir Bostad 的回答是正确的;我的回应只是为了提供一个示例和可能的解决方法,因为人们经常无法理解这一点。除了在另一个答案中引用的 Wiki 页面之外,还有一个单独的 Wiki 页面仅用于示例,其中包括一个“存款报告”示例,该示例将批次视为已关闭但尚无法查看批次的最终详细信息。
热备是只读的,所以只能看到瞬态序列化异常;数据最终会在一些后续事务中进入一致状态。这与主服务器上的可重复读取事务可能发生的情况相同,而主服务器上的可序列化事务不可能发生这种情况。为防止混淆,热备用上不允许可序列化事务,因为您(还)不能保证在那里看到真正可序列化的事务行为。已经有将信息添加到WAL流,其识别序列化交易可能没有看到异常情况,类似的风险开始点的通话DEFERRABLE的选项START TRANSACTION; 这个(或类似的东西)很可能会在未来的某个版本中添加。
对于使用快照隔离的只读事务(包括在 Oracle 或 9.1 之前的 PostgreSQL 版本中标识为可序列化的事务),最常见的异常类型似乎是 SELECT 列表或汇总在事务中显示为“已关闭”的批处理,没有看到应该包含在批次中的所有工作。要看到这一点,关闭批处理的事务必须“重叠”(同时运行)一些修改批处理详细信息的事务,关闭批处理的事务必须首先提交,然后(在关闭批处理的事务提交之后和修改批处理详细信息的事务之前)提交)只读事务必须启动并获取其快照。
为了防止这种情况,最简单的技术是在主节点上“促进冲突”,从读写依赖关系到写写冲突。例如,在上面引用的“存款报告”示例中,可以将 deposit_total 列添加到控制表中,当 deposit_no 递增时,可以将 AFTER 触发器设置为零,并且可以将 AFTER 触发器添加到收据表中以更新金额基于每张收据的金额。这将导致基于控制记录的写入冲突的序列化失败,从而阻止异常传播到副本。