一个 postgres SELECT 查询在我们的数据库服务器上失控并开始消耗大量内存和交换,直到服务器内存耗尽。ps aux | grep postgres
我通过并运行找到了特定的过程kill -9 pid
。这终止了进程并按预期释放了内存。系统的其余部分和 postgres 查询似乎不受影响。此服务器在 SLES 9 SP4 上运行 postgres 9.1.3。
然而,我们的一位开发人员斥责我用 终止了一个 postgres 进程kill -9
,说这将关闭整个 postgres 服务。事实上,它没有。我以前做过几次,没有看到任何负面影响。
话虽如此,在进一步阅读之后,看起来kill pid
没有标志是杀死失控的 postgres 进程的首选方法,但对于 postgres 社区的其他用户来说,这听起来也像 postgres 这些年来“变得更好”,以至于kill -9
在单个查询进程/线程上不再是死刑。
有人能告诉我杀死失控的 postgres 进程的正确方法以及kill -9
这些天使用 Postgres 的灾难性(或良性)吗?感谢您的洞察力。
voretaq7的回答涵盖了关键点,包括终止后端的正确方法,但我想补充一点解释。
kill -9
(ieSIGKILL
) 永远、永远、永远不应该成为您的首选默认值。SIGTERM
当进程不响应其正常的关闭请求并且(kill -15
) 没有效果时,这应该是您最后的选择。Pg 和几乎所有其他东西都是如此。kill -9
让被杀死的进程根本没有机会进行任何清理。当涉及到 PostgreSQL 时,Pg 将终止于 backed by
kill -9
的 backed 视为 backed crash。它知道后端可能损坏了共享内存——因为你可以在将页面写入 shm 或修改一个页面的过程中中断它,例如——所以当它注意到后端突然消失时,它会终止并重新启动所有其他后端并以非零错误代码退出。您会在日志中看到此报告。
如果它看起来没有任何危害,那是因为 Pg 在崩溃后重新启动了所有内容,并且您的应用程序正在从丢失的连接中完全恢复。这不是一个好主意。如果没有其他后端崩溃测试不如 Pg 的正常功能部分那么好,并且更加复杂/多变,那么后端崩溃处理和恢复中潜伏错误的可能性更高。
顺便说一句,如果你
kill -9
是 postmaster 然后postmaster.pid
在没有确保每个postgres
后端都消失的情况下删除并重新启动它,那么可能会发生非常糟糕的事情。如果您不小心杀死了 postmaster 而不是后端,看到数据库已经关闭,试图重新启动它,在重新启动失败时删除“陈旧的”.pid 文件,然后再次尝试重新启动它,这很容易发生。这就是你应该避免kill -9
在 Pg 周围挥手而不应该删除的原因之一postmaster.pid
。演示:
要准确查看后端时会发生什么
kill -9
,请尝试这些简单的步骤。打开两个终端,在每个终端中打开 psql,并在每个终端中运行SELECT pg_backend_pid();
。在另一个终端kill -9
中,其中一个 PID。现在SELECT pg_backend_pid();
再次在两个 psql 会话中运行。注意到他们是如何失去联系的吗?我们杀死的第 1 节:
会话 2,这是附带损害:
看看两个会话是如何中断的?这就是为什么你没有
kill -9
后端。I found the particular process via ps aux | grep postgres and ran kill -9 pid.
不!坏的!远离后端!
说真的——不要那样杀死 Postgres 后端——可能会发生可怕的事情(即使自 7.x 以来已经进行了所有稳定性增强)这可能会破坏你的整个数据库,你的开发人员是非常正确的咀嚼你出去做这个。
事实上,在 Postgres 中有一种被认可的方法可以做到这一点——它甚至在Postgres 手册中都有,尽管 SO 帖子在解释它方面做得更好......
SELECT pg_cancel_backend(pid)
向指定的后端发送取消 (
SIGINT
) 信号,取消当前正在运行的查询。select pg_terminate_backend(pid)
向指定的后端发送终止 (
SIGTERM
) 信号,这会取消查询并中止后端(断开其连接)。可以从
pg_stat_activity
表(或ps
)中获取后端 ID终止 PostgreSQL 客户端进程应该没问题。杀死 PostgreSQL 守护进程可能会让你挨骂。
由于 SQL 守护进程也有内部进程控制,因此首选方法是首先尝试使用该通道。
请参阅StackOverflow中的停止(长时间)在 PostgreSQL 中运行 SQL 查询...。