Как я могу изящно убить устаревшие серверные процессы postgres

Иногда в нашей лаборатории наша база данных postgres 8.3 будет потеряна из pid файла, и мы получим это сообщение при попытке закрыть базу данных:

Error: pid file is invalid, please manually kill the stale server process postgres

Когда это произойдет, мы немедленно сделаем pg_dump, чтобы позже восстановить базу данных. Но если мы просто убиваем -9 процесс сирота postgres, а затем запускаем его, база данных начинается только с данных последнего успешного завершения. Но если вы psql к нему, прежде чем убить его, все данные доступны, поэтому работает pg_dump.

Есть ли способ изящно закрыть процесс осиротевших postgres, поэтому нам не нужно проходить через pg_dump и восстанавливать? Или есть способ восстановить базу данных после убийства осиротевшего процесса?

Ответ 1

В соответствии с документацией вы можете отправить SIGTERM или SIGQUIT. SIGTERM является предпочтительным. В любом случае никогда не используйте SIGKILL (как вы знаете из личного опыта).

Изменить:, с другой стороны, то, что вы испытываете, не является нормальным и может указывать на неправильную конфигурацию или ошибку. Пожалуйста, обратитесь за помощью в список рассылки pgsql-admin.

Ответ 2

Никогда используйте kill -9.

И я бы настоятельно советовал вам попытаться выяснить, как это происходит. Откуда возникает сообщение об ошибке? Это не сообщение об ошибке PostgreSQL. Вы случайно можете смешивать разные способы запуска/остановки сервера (иногда иногда initscripts и pg_ctl)? Вероятно, это может привести к сбоям в синхронизации.

Но для ответа на прямой вопрос - используйте обычный kill (no -9) для процесса, чтобы его закрыть. Убедитесь, что вы убили все процессы postgres, если есть более одного запуска.

База данных всегда будет выполнять автоматическое восстановление всякий раз, когда она отключается. Этот shuold случается с kill -9, а также любые данные, которые были зафиксированы, должны быть там. Это почти похоже на то, что у вас есть два разных каталога данных, установленные друг на друга или что-то в этом роде - это была известная проблема с NFS, по крайней мере до этого.

Ответ 3

Я использую script, как и следующий запуск cron каждую минуту.

#!/bin/bash

DB="YOUR_DB"

# Here a snippet to watch how long each connection to the db has been open:
#     watch -n 1 'ps -o pid,cmd,etime -C postgres | grep $DB'

# This program kills any postgres workers/connections to the specified database
# which have been running for 2 or 3 minutes. It actually kills workers which
# have an elapsed time including "02:" or "03:". That'll be anything running
# for at least 2 minutes and less than 4. It'll also cover anything that
# managed to stay around until an hour and 2 or 3 minutes, etc.
#
# Run this once a minute via cron and it should catch any connection open
# between 2 and 3 minutes. You can temporarily disable it if if you need to run
# a long connection once in a while.
#
# The check for "03:" is in case there a little lag starting the cron job and
# the timing is really bad and it never sees a worker in the 1 minute window
# when it got "02:".
old=$(ps -o pid,cmd,etime -C postgres | grep "$DB" | egrep '0[23]:')
if [ -n "$old" ]; then
    echo "Killing:"
    echo "$old"
    echo "$old" | awk '{print $1}' | xargs -I {} kill {}
fi