作者:瀚高PG实验室 (Highgo PG Lab)- Kalath
在PostgreSQL流复制环境下,备用服务器上进行查询时,日志输出中可能会出现这类报错。
问题原因
当备用服务器在WAL流中获取更新/删除,而且该更新/删除将使正在运行的查询当前正在访问的数据无效,在这种情况下将发生此类错误。
例如,主服务器在备用服务器正在查询的表上运行DROP TABLE命令。显然,此时备用服务器上的查询无法继续。当在主服务器上运行DROP TABLE命令时,它不会等待备用服务器上的查询。当备用服务器上的查询仍在运行时,WAL的更改记录进入备用数据库,从而导致冲突。
当冲突的查询很短时,可以通过稍微延迟WAL应用进程来使它完成。但是WAL应用进程的长时间延迟通常是不可取的。max_standby_archive_delay和max_standby_streaming_delay参数定义了WAL应用进程中允许的最大延迟。一旦超过max_standby_archive_delay或max_standby_streaming_delay指定的延迟,冲突的查询将被取消。这通常会导致取消错误。
解决方法
有三种方法可以避免这种查询取消的情况:
1)在备用数据库上设置hot_standby_feedback=on,它将传递信息给主数据库,表示仍然需要表中的特定行,这可以防止VACUUM操作删除最近的死行,避免发生清除冲突。它允许备用服务器上的查询能够可靠地完成,但是将导致主服务器上的膨胀现象,当备用服务器上的查询长时间不结束时,此膨胀现象尤为明显。
2)提高max_standby_archive_delay或者max_standby_streaming_delay参数。如果备用服务器会频繁的连接和断开连接,可能需要进行调整以处理hot_standby_feedback未提供反馈的时间段。但如果将它们的值设置的过大(例如1小时),主服务器和备用服务器的状态可能会出现不一致的情况。
3)提高主服务器上的vacuum_defer_cleanup_age参数,避免快速的清除死行。这将给备用数据库上的查询更多时间来在被取消之前执行,而无需设置一个很高的max_standby_streaming_delay值。但是,使用这种方法时,执行时间很难保证,因为vacuum_defer_cleanup_age是在主服务器上执行的事务中被测量的。
综上所述,建议使用第一种解决方案。