1、什么是查询冲突?
由于primary服务器和standby服务器是相互连接的。因此,一些primary服务器上的操作也会对standby服务器产生影响,如一些负面的交互或冲突。
最容易理解的冲突是“performance”:例如primary服务器上负载很大,那么standby服务器上也会生成类似的WAL记录流,因此standby上的查询可能会争用系统资源,比如I/O。
另外,Hot Standby还可能发生其他类型的冲突。这些冲突被称为硬冲突(hard conflicts),因为可能需要取消查询。甚至在某些情况下,还需要断开会话以解决这些冲突。
2、出现查询冲突的几种场景
出现冲突场景包括:
a、操作冲突
-
在primary服务器上使用Access Exclusive锁,包括显式LOCK命令和各种DDL操作,与standby查询中的表访问冲突。
-
在primary服务器上drop一个tablespace与在standby服务器使用该tablespace用于temporary work files的查询冲突。
-
在primary服务器上drop一个database与在standby服务器上连接到该database的会话发生冲突。
b、清理冲突
-
来自WAL的vacuum cleanup record应用程序与standby transactions的冲突,standby事务的快照仍然可以“看到”要移除的任何行。
-
来自WAL的vacuum cleanup record应用程序与访问standby服务器上target page的查询发生冲突,无论要移除的数据是否可见。
3、发生冲突的数据库默认行为
-
在primary服务器上,查询将会等待。
-
在standby服务器上,查询将等待30s(因为max_standby_archive/streaming_delay的默认值为30s),然后会被取消,甚至断开连接。因为,在standby服务器上,由于WAL-logged的操作已经在primary服务器上发生了,所以standby服务器不能失败地应用它。
举例来说:
primary服务器上的管理员对当前正在standby服务器上查询的表运行DROP TABLE。显然,如果在standby数据库上应用了DROP TABLE,standby查询将无法继续。如果这种情况发生在primary数据库上,那么DROP TABLE将等待其他查询完成。但是当在primary服务器上运行DROP TABLE时,primary服务器没有关于在standby服务器上运行的查询的信息,因此它不会等待任何这样的standby查询。当standby查询仍在运行时,WAL更改记录将传递到standby查询,从而导致冲突。standby服务器必须延迟应用WAL记录(以及之后的所有记录),或者取消冲突的查询,以便应用DROP TABLE。
4、处理查询冲突的机制
a、延迟备库上的WAL应用
使用如下参数:
-
max_standby_archive_delay:定义从archive读取WAL数据(即,从base backup进行初始恢复(initial recovery)或“catch up”远远落后的standby服务器)延迟值,默认值为30s。 (在standby设置)
-
max_standby_streaming_delay:定义通过流复制读取WAL数据的延迟值,默认值值为30s。 (在standby设置)
其定义了WAL应用程序中允许的最大延迟。一旦应用任何新接收到的WAL数据所需的时间超过dalay设置,standby上的冲突查询将被取消。delay参数是与standby服务器上接收到WAL数据后所经过的时间(elapsed time)进行比较的。因此,standby服务器上任何一个查询允许的宽限期永远不会超过delay参数值。
b、延迟主库上的VACUUM操作
当standby上被取消查询的数量不可接受时,可以使用如下参数:
- hot_standby_feedback:设置此参数,可以防止primary库VACUUM删除最近的死元组,这样就不会发生清理冲突(cleanup conflicts)。 (在standby设置)
使用此方法将延迟清理primary数据库上的死元组,这可能导致表膨胀。但是,清理情况不会比直接在primary服务器上运行standby查询更糟糕,并且仍然可以从将执行卸载到standby服务器上获得好处。
However, the cleanup situation will be no worse than if the standby queries were running directly on the primary server, and you are still getting the benefit of off-loading execution onto the standby.
- vacuum_defer_cleanup_age:通过增加此参数的值,可以延缓VACUUM删除最近的死元组。(在primary设置)
使用此方法将允许在standby服务器上取消查询之前有更多的时间执行查询,而不必设置较高的max_standby_streaming_delay。然而,使用这种方法很难保证任何特定的执行时间窗口,因为vacuum_defer_cleanup_age是在priamry服务器上执行的事务中度量的。
5、监控查询冲突事件
a、通过系统视图
- pg_stat_database_conflicts:查看查询取消的数量及其原因
- pg_stat_database:可以查询冲突的摘要信息。
如:

b、通过错误日志

参考资料
https://www.postgresql.org/docs/12/hot-standby.html#HOT-STANDBY-CONFLICT




