PostgreSQL 9.1 потоковая репликация restore_command: особое значение кода выхода 255?

У меня есть настройка потоковой репликации PostgreSQL 9.1.3 на Ubuntu 10.04.2 LTS (основная и резервная). Репликация инициализируется потоковой базовой резервной копией (pg_basebackup). Скрипт restore_command пытается получить требуются архивы WAL из удаленного архива с rsync.

Все работает, как описано в документации, когда сценарий restore_command не работает с код выхода ‹> 255:

При запуске резервный запускается с восстановления всего WAL, доступного в расположении архива, вызывая restore_command. Когда он достигает конца доступного там WAL и команда restore_command завершается неудачно, он пытается восстановить любой WAL, доступный в каталоге pg_xlog. Если это не удается и потоковая репликация настроена, резервный пытается подключиться к первичному серверу и начать потоковую передачу WAL с последней действительной записи, найденной в архиве или pg_xlog. Если это не удается или потоковая репликация не настроена, или если соединение позже разрывается, резервный возвращается к шагу 1 и снова пытается восстановить файл из архива. Этот цикл повторных попыток из архива pg_xlog и потоковой репликации продолжается до тех пор, пока сервер не будет остановлен или пока не будет запущено переключение при отказе файлом триггера.

Но когда сценарий restore_command завершается с ошибкой с кодом выхода 255 (потому что код выхода из неудачного вызова rsync возвращается сценарием), серверный процесс умирает со следующей ошибкой:

2012-05-09 23:21:30 CEST - @  LOG:  database system was interrupted; last known up at     2012-05-09 23:21:25 CEST
2012-05-09 23:21:30 CEST - @  LOG:  entering standby mode
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: unexplained error (code 255) at io.c(601) [Receiver=3.0.7]
2012-05-09 23:21:30 CEST - @  FATAL:  could not restore file "00000001000000000000003D" from archive: return code 65280
2012-05-09 23:21:30 CEST - @  LOG:  startup process (PID 8184) exited with exit code 1
2012-05-09 23:21:30 CEST - @  LOG:  aborting startup due to startup process failure

Итак, мой вопрос теперь: это ошибка или есть особое значение кода выхода 255, которое отсутствует в отличной документации, или мне здесь не хватает чего-то еще?


person tscho    schedule 09.05.2012    source источник
comment
Я не делаю этого ответа прямо сейчас, потому что у меня нет времени проверять исходный код, чтобы подтвердить его позже или завтра, но я помню, что при применении файлов WAL во время восстановления ненулевой код выхода меньше, чем 255 означает неудачу, но продолжайте попытки, а 255 (или выше) означает неудачную попытку; сдаться. Возможно, вам придется настроить ваш скрипт, чтобы он возвращал меньший код выхода для ошибки rsync.   -  person kgrittn    schedule 10.05.2012
comment
@kgrittn: Спасибо, я думал о чем-то вроде этого, но я не смог найти никакой документации, касающейся особого значения кода выхода 255, и я не знаю, где его искать в исходном коде.   -  person tscho    schedule 10.05.2012
comment
Эээ, это заняло некоторое время, но это снова всплыло как вопрос, с которым мне пришлось иметь дело, и на мой комментарий здесь была ссылка, поэтому я просмотрел его и опубликовал ответ с подробностями. На этот раз я попробую добавить что-нибудь в документацию ...   -  person kgrittn    schedule 25.10.2016


Ответы (4)


На первичном сервере в каталоге pg_xlog/ находятся WAL файлы. Пока есть WAL файлы, PostgreSQL может доставить их в резервный сервер, если они будут запрошены.

Как правило, у вас также есть локальное хранилище WAL в архиве, когда файлы перемещаются туда с помощью PostgreSQL, они больше не могут быть доставлены в резервный он-лайн, и резервный сервер ожидает, что они поступят из хранилища WAL в архиве через restore_command.

Если у вас есть разные места для установки заархивированных WALs на основном и резервном серверах, то какое-то время нет возможности перейти в резервный, и у вас есть пробел.

В вашем случае это может означать, что:

  • 00000001000000000000003D был заархивирован основным PostgreSQL;
  • Резервный restore_command не видит его из настроенного исходного местоположения.

Вы можете вручную скопировать отсутствующие файлы WAL с основного на резервный, используя scp или rsync. Также может потребоваться просмотреть ваши WAL местоположения и убедиться, что оба сервера смотрят в одном направлении.


РЕДАКТИРОВАТЬ: grep-ing для restore_command в источниках, только access/transam/xlog.c ссылается на него. В функции RestoreArchivedFile почти в конце (круглая строка 3115 для источников 9.1.3) есть проверка, завершился ли restore_command нормально или он получил сигнал.

В первом случае сообщение классифицируется как DEBUG2. В случае, если restore_command получил сигнал, отличный от SIGTERM (и, я полагаю, не смог его обработать должным образом), будет сообщено об ошибке FATAL. Это верно для всех кодов больше 125.

Однако я не смогу сказать вам, почему.
Я рекомендую спросить в списке хакеров .

person vyegorov    schedule 09.05.2012
comment
Спасибо за ответ, но я спрашивал не об этом. Я знаю, почему restore_command не работает, и как я могу это исправить, дело не в этом. Фактически, команда restore_command должна в какой-то момент потерпеть неудачу. У меня вопрос: почему код выхода ›0, но‹ ›255 имеет другой эффект, чем код выхода 255. С кодом выхода 255 процесс резервного сервера умирает, а он должен продолжать цикл восстановления, как он с кодом выхода 1 или 17. - person tscho; 10.05.2012
comment
Спасибо за редактирование с указанием местоположения исходного кода. Я посмотрю на это. - person tscho; 10.05.2012

Это похоже на проблему с rsync, с которой я столкнулся временно при использовании NFS (с rpcbind / rstatd на порту 837):

$ rsync -avz /var/backup/* backup@storage:/data/backups
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(600) [sender=3.0.6]

Это исправило это для меня:

service rpcbind stop
person bbaassssiiee    schedule 27.05.2014

У меня была такая же проблема с созданием горячего резерва (postgres 9.5). Потоковая передача работала (я засеял резервный сервер через pg_basebackup, используя те же учетные данные, которые позже будут использоваться в резервном recovery.conf).

После создания базовой резервной копии я установил следующий файл recovery.conf:

standby_mode = 'on'
primary_conninfo = 'host=ip.of.master port=5432 user=pgstandby password=password'
recovery_target_timeline = 'latest'
restore_command = 'sftp -q [email protected]:data/master_wal_archive/%f "%p"'
trigger_file = '/srv/pgsql/9.5/data/trigger'

Запуск сервера даст:

2016-03-08 12:34:58.981 UTC  (/)LOG:  database system was interrupted; last known up at 2016-03-08 12:26:10 UTC
Couldn't read packet: Connection reset by peer
2016-03-08 12:34:59.525 UTC  (/)FATAL:  could not restore file "00000002.history" from archive: child process exited with exit code 255
2016-03-08 12:34:59.526 UTC  (/)LOG:  startup process (PID 26636) exited with exit code 1
2016-03-08 12:34:59.526 UTC  (/)LOG:  aborting startup due to startup process failure

Если я удалил строку restore_command из recovey.conf, резервный сервер запустился нормально и начал потоковую передачу WAL от мастера.

В конце концов я проследил проблему до того, что я не добавил открытый ключ резервного пользователя postgres в файл authorized_hosts хоста архива WAL. Я также забыл добавить отпечаток сервера хоста архива WAL в файл known_hosts резервного пользователя postgres.

Эти две ошибки были (я предполагаю), что sftp restore_command завершился с кодом 255. Как говорит tscho, документы Postgres предполагают, что если restore_command завершится с ЛЮБЫМ ненулевым значением, Postgres просто перейдет к попытке потоковой передачи от мастера вместо того, чтобы отказываться начинать. На самом деле это не так, если код выхода больше определенного числа (может быть, 125, как подсказывает grepping исходного кода vyegorov?).

Как только я исправил две проблемы с SSH, резервный сервер нормально запустился с помощью restore_command, присутствующей в recovery.conf.

person corford    schedule 08.03.2016

Вот комментарий, описывающий, почему было выбрано это поведение для высокого статуса выхода из командного процесса, и текущий код для его реализации.

    /*
     * Remember, we rollforward UNTIL the restore fails so failure here is
     * just part of the process... that makes it difficult to determine
     * whether the restore failed because there isn't an archive to restore,
     * or because the administrator has specified the restore program
     * incorrectly.  We have to assume the former.
     *
     * However, if the failure was due to any sort of signal, it's best to
     * punt and abort recovery.  (If we "return false" here, upper levels will
     * assume that recovery is complete and start up the database!) It's
     * essential to abort on child SIGINT and SIGQUIT, because per spec
     * system() ignores SIGINT and SIGQUIT while waiting; if we see one of
     * those it's a good bet we should have gotten it too.
     *
     * On SIGTERM, assume we have received a fast shutdown request, and exit
     * cleanly. It's pure chance whether we receive the SIGTERM first, or the
     * child process. If we receive it first, the signal handler will call
     * proc_exit, otherwise we do it here. If we or the child process received
     * SIGTERM for any other reason than a fast shutdown request, postmaster
     * will perform an immediate shutdown when it sees us exiting
     * unexpectedly.
     *
     * Per the Single Unix Spec, shells report exit status > 128 when a called
     * command died on a signal.  Also, 126 and 127 are used to report
     * problems such as an unfindable command; treat those as fatal errors
     * too.
     */
    if (WIFSIGNALED(rc) && WTERMSIG(rc) == SIGTERM)
        proc_exit(1);

    signaled = WIFSIGNALED(rc) || WEXITSTATUS(rc) > 125;

    ereport(signaled ? FATAL : DEBUG2,
            (errmsg("could not restore file \"%s\" from archive: %s",
                    xlogfname, wait_result_to_str(rc))));
person kgrittn    schedule 25.10.2016