如何正确停止PostgreSQL stats collector?重启异常问题求助
首先得划个重点:绝对不要手动kill PostgreSQL的子进程(包括stats collector)。PostgreSQL是一套协同工作的进程集群,主进程会时刻监控这些子进程,你手动杀掉子进程后,主进程会立刻重启它——这就是你用kill -9没效果的原因,而且这么做还可能引发数据一致性风险,甚至损坏数据库。
一、先试标准的PostgreSQL停止流程
先别着急硬来,先用官方推荐的停止命令:
- 如果你的系统用systemd管理(大部分现代Linux发行版都是):
sudo systemctl stop postgresql - 要是用init.d脚本:
sudo /etc/init.d/postgresql stop - 源码安装或自定义部署的话,用pg_ctl:
pg_ctl stop -D /你的postgres数据目录路径 -m fast
这里的-m fast很关键,它会强制终止所有活跃连接,然后干净关闭数据库,比默认等待连接自行断开高效得多。
二、为什么kill -9 stats collector没用?
Stats collector是PostgreSQL的核心辅助进程,主进程会把它当成必要组件,一旦检测到它被杀死,会马上重启一个新的出来——你看到的stats collector进程,大概率已经是主进程重启后的新实例了。
另外看你贴的ps -aux输出,还有个idle状态的连接:postgres: dbname: postgres sakura 127.0.0.1(56496) idle waiting for D1E/CEA4D9C8,这个连接很可能是阻碍正常关闭的元凶:PostgreSQL默认会等所有活跃连接断开才会关闭,除非你用fast或者immediate模式强制停止。
三、强制但相对安全的关闭方式
如果标准停止命令没效果,可以试试immediate模式(注意:这个模式类似强制断电,会跳过部分清理操作,重启时PostgreSQL会自动做恢复,虽然安全但尽量少用):
pg_ctl stop -D /你的postgres数据目录路径 -m immediate
或者用systemd的强制终止命令,直接给主进程发SIGKILL,这样主进程会终止所有子进程并退出,不会再重启它们:
sudo systemctl kill -s SIGKILL postgresql
四、后续排查:为什么会出现这种情况?
- pg_stat_statements的潜在影响:pg_stat_statements本身一般不会导致进程僵死,但如果分析时执行了极耗时的PL/pgSQL函数,可能导致连接长时间持有;或者扩展版本和PostgreSQL版本不兼容,也可能引发异常。重启后可以检查下
pg_stat_statements的版本是否和你的PostgreSQL版本匹配。 - 查日志找根源:去PostgreSQL的日志目录(一般是
/var/log/postgresql/或者数据目录下的pg_log)看日志,里面会记录无法正常关闭的具体原因,比如哪个事务卡住了、哪个锁没释放等。 - 先处理卡住的连接:在尝试停止数据库前,可以先手动终止那个idle的连接:
先登录PostgreSQL:
然后查询所有活跃连接:psql -U postgres
找到那个卡住的连接的pid(就是你ps输出里的23030),执行终止命令:SELECT pid, datname, usename, state FROM pg_stat_activity;
之后再尝试正常停止数据库。SELECT pg_terminate_backend(23030);
总结
永远优先用官方的停止命令,别手动杀子进程;遇到停不了的情况,先终止卡住的连接,再用fast模式停止;万不得已再用immediate模式。重启后一定要检查数据库日志,确认没有异常情况。
内容的提问来源于stack exchange,提问作者kiitosu

