org.postgresql.util.PSQLException:错误:由于与恢复冲突而取消语句

Gon*_*uez 3 postgresql data-synchronization postgresql-9.4 master-slave-replication

我目前有一个 PostgreSQL 从属节点存在问题,但在主节点中不会出现这些问题。似乎与节点同步过程有关。

完整的堆栈跟踪:

org.postgresql.util.PSQLException: ERROR: canceling statement due to conflict with recovery
  Detail: User query might have needed to see row versions that must be removed.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
    at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:82)
    at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:82)
    at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.java:542)
    at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.java:518)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes.updateIgnicion(StatusSemanalClientes.java:448)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes.access$2(StatusSemanalClientes.java:447)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.java:414)
    at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.java:1)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Run Code Online (Sandbox Code Playgroud)

数据库版本:

PostgreSQL 9.4.9 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
Run Code Online (Sandbox Code Playgroud)

操作系统版本:

Distributor ID: Debian
Description:    Debian GNU/Linux 8.6 (jessie)
Release:    8.6
Codename:   jessie
Run Code Online (Sandbox Code Playgroud)

问题是:如何调试问题的实际原因和/或解决/避免它?如果需要查明问题,请毫不犹豫地询问更多信息,现在只是不知道还可以提供什么。

PS:如果重复有问题的查询,则不会出现错误,因此它与查询本身并不严格相关,但可能与表更新/同步瞬态有关。

dez*_*zso 5

对于在主服务器上运行备用数据库和更大查询的任何人来说,您所看到的都是常见的体验。有几个可能的原因

热备还可能发生其他类型的冲突。这些冲突是硬冲突,因为可能需要取消查询,并且在某些情况下,需要断开会话才能解决它们。为用户提供了多种方法来处理这些冲突。冲突案例包括:

在主服务器上采取的访问独占锁(包括显式 LOCK 命令和各种 DDL 操作)与备用查询中的表访问发生冲突。

  • 在主数据库上删除表空间与使用该表空间作为临时工作文件的备用查询会发生冲突。
  • 删除主数据库上的数据库与连接到备用数据库上该数据库的会话发生冲突。
  • 从 WAL 中应用真空清理记录与备用事务发生冲突,备用事务的快照仍然可以“看到”任何要删除的行。
  • 无论要删除的数据是否可见,应用来自 WAL 的清理清理记录都会与访问备用数据库上的目标页的查询发生冲突。

查询何时会因上述原因之一而被终止很难预测,但通常有一些原因出现得更频繁。它也是可配置的,有关选项请进一步阅读文档页面。

最重要的选项是hot_standby_feedback,它有助于解决最常见的原因(VACUUM删除最近死亡的行)。它有自己的成本(可能会导致表膨胀),但结果通常仍然比在主服务器上运行相同的查询更好。