如果连接丢失/中断,Postgres 长时间运行的查询是否会中止?

Rob*_*ark 25 postgresql connections

如果我打开到 Postgres 的连接并发出长时间运行的查询,然后断开连接(例如,终止打开连接的客户端进程),长时间运行的查询会继续运行,还是会自动中止?这个可以配置吗?

(我使用的是 Postgresql 9.2.9)

Cra*_*ger 42

“这取决于”。

如果客户端由于网络连接丢失而消失,则查询通常会运行,直到它检索到足够的行来填充其网络发送缓冲区,然后停止并卡住,直到 TCP 连接断开,此时它将中止。如果它填充 TCP 发送缓冲区之前完成它将成功完成,因此如果它是自动提交,则查询将提交。

如果客户端以客户端的操作系统可以通过 TCP RST 报告给服务器的方式被终止(如客户端段错误/崩溃、SIGTERM、SIGKILL 等),PostgreSQL 服务器将设置中断标志。下次查询在执行时检查中断时,它将看到标志并中止。有时,查询可能会在不检查中断的代码中执行占用大量 CPU 的工作——一些扩展,以及 PostgreSQL 核心中的一些地方——在这种情况下,它可能很长时间没有注意到中断并继续运行。但是,如果它是自动提交,它几乎总是会在完成和提交之前看到中断和中止。

如果客户端被操作系统突然重启之类的事情杀死,以至于客户端主机突然对 TCP 连接一无所知但仍然可以在网络上响应,则查询可能会在第一次尝试写入行时中止,例如Jeff 说,因为客户端的主机会发送一个 TCP RST 来响应重启后服务器发送的第一个数据包。PostgreSQL 在它发送的每一行检查中断。

此行为不可配置。就 PostgreSQL 而言,如果客户端消失,它的工作是终止客户端正在运行的任何查询。要更改它,您需要某种可以在查询开始时获取的查询完成令牌,然后用于稍后通过另一个连接向服务器询问查询。本质上,您必须实现异步/后台查询。可能是一个不错的功能,但目前不支持。

如果查询是自动提交的,或者如果您的查询COMMIT在您杀死客户端/失去连接时正在进行中,则事务可能处于不确定状态,客户端不知道是否或不是它犯了。除了寻找交易对数据的影响之外,没有真正的方法可以找出答案。

如果这是不可接受的,您可以使用两阶段提交和客户端事务管理器。


jja*_*nes 5

它将继续运行,直到尝试将行返回到连接并检测到损坏。因此,对于在返回任何行之前完成所有工作的查询,它基本上会运行到完成。

  • 谢谢@jjanes。您能指出任何表明这一点的文档或源代码吗? (2认同)