Como esperar que o PostgreSQL seja inicializável / restaurável?

8

Estou testando uma atualização do PostgreSQL 8.2.1 para 9.2 em uma máquina virtual executando uma distribuição Linux personalizada. O procedimento de atualização é o seguinte:

  1. Iniciar o pgserviço
  2. Vácuo todos os DBs (não tenho certeza se isso é necessário)
  3. Backup com pg_dumpall
  4. Interrompa o pgserviço
  5. Afaste o diretório em que os dados estão armazenados ( /var/pg; é uma configuração simples de servidor único)
  6. Instale o PostgreSQL 9.2
  7. initdb
  8. Iniciar o servidor
  9. Restaurar os dados despejados
  10. reindexdb todos os bancos de dados
  11. Recrie a referential_constraintsvisualização
  12. Limpe todos os DBs (é necessário o AFAIK após esta atualização)

Este procedimento funciona bem em um host, fazendo backup e restaurando sem problemas. Em outra máquina com um banco de dados diferente, os pontos 1 a 7 funcionam bem, mas o servidor não inicia a menos que eu adicione um sleep 1depois initdb, e mesmo assim os dados despejados não podem ser restaurados porque "o sistema do banco de dados está inicializando". Quais são as formas padrão de lidar com isso, exceto por esses terríveis hacks:

  1. sleeppor um período generoso de tempo antes de qualquer operação,
  2. até que funcione ou até que um tempo limite generoso seja alcançado, ou
  3. até aceitar uma consulta trivial ou atingir um tempo limite.

Edit: A " solução " não funcionou, afinal. O que é necessário para garantir que o banco de dados esteja pronto para executar uma restauração?

l0b0
fonte
Apenas uma idéia: você pode testar o initdbstatus de saída? Suponho que quando o trabalho estiver pronto.
Dez16
@dezso Não, initdbé executado de forma síncrona, portanto, quando o servidor é iniciado, ele initdbjá foi concluído com êxito.
L0b0 16/10/12
Então, não tenho idéia melhor do que fazer um teste simples que verifica se as coisas estão prontas.
Dez16
2) não é necessário. 10) também não é necessário, pois a restauração do despejo recriará todos os índices.
a_horse_with_no_name

Respostas:

5

O initdb não retorna até que esteja concluído; portanto, não deve haver nenhuma pausa entre ele e a inicialização do servidor. Houve erros no PostgreSQL, onde ele foi concluído sem liberar tudo para o disco primeiro. Não conheço nenhuma esquerda agora, mas a natureza dos bugs é que você nem sempre sabe sobre eles.

Se você usar o comando pg_ctl para iniciar o banco de dados, use os parâmetros "-w" para aguardar até que a inicialização seja concluída antes de retornar. Não faz nada extravagante - apenas faz o "já está pronto?" loop para você.

Observe que, se ocorrer uma falha no servidor com muitos dados que precisam ser reproduzidos antes que o servidor possa iniciar, o tempo limite definido por "-t" na espera do pg_ctl poderá ser muito baixo.

Não há motivo para VACUUM os bancos de dados de origem antes de fazer um pg_dump deles. Embora possa acelerar um pouco o despejo, o próprio vácuo levará mais tempo do que essa melhoria.

Greg Smith
fonte
A 12. etapa é necessária? Eu esperaria que as tabelas fossem contíguas (ou quase contíguas após um pg_restore -j{morethan1}).
Dez17
Estamos correndo postmasterpara iniciar o daemon, e ele não parece ter essa opção.
L0b0 17/10/12
2

o trabalhandoA solução quebrada foi modificar o script init para verificar repetidamente se a porta relevante está em uso. Se não aparecer após um minuto, a inicialização é considerada como tendo falhado. Pseudo-código:

start() {
    pg start
    checks=0
    while checks < 30:
        return true if the port is in use
        sleep 2
        checks++
    return false
}

Edit: Acontece que isso não é suficiente. A etapa de restauração:

PGOPTIONS='--client-min-messages=warning' psql \
    --no-psqlrc \
    --variable=ON_ERROR_STOP=1 \
    --quiet \
    --log-file="$restore_log" \
    --single-transaction \
    --username postgres \
    --file="$sql_backup"

Mensagem de erro:

psql: FATAL:  the database system is starting up
l0b0
fonte