Estou tentando saber quando minha tabela foi modificada verificando sua data de modificação do arquivo, conforme descrito nesta resposta . Mas o resultado nem sempre é correto. A data de modificação do arquivo é atualizada em alguns minutos após a atualização da minha tabela. É um comportamento correto? O PostgreSQL armazena modificações de tabelas em algum cache e depois as libera para o disco rígido?
Então, como obtenho a data correta da última modificação de uma tabela (vamos supor que as modificações automáticas de vácuo também estejam corretas)?
Eu uso o PostgreSQL 9.2 no Linux Centos 6.2 x64.
postgresql
hank
fonte
fonte
Respostas:
Não há nenhum registro confiável e autoritário do horário da última modificação de uma tabela. O uso do relfilenode está errado por vários motivos:
As gravações são inicialmente registradas no WAL (write-head log) e depois preguiçosamente no heap (os arquivos da tabela). Quando o registro está no WAL, a página não se apressa em gravá-lo no heap e pode até não ser gravado até o próximo ponto de verificação do sistema;
Tabelas maiores têm vários garfos, você precisará verificar todos os garfos e escolher o carimbo de data / hora mais recente;
Um simples
SELECT
pode gerar atividade de gravação na tabela subjacente devido à configuração do bit de dica;autovaccum e outras manutenções que não alteram os dados visíveis do usuário ainda modificam os arquivos de relação;
algumas operações, como
vaccum full
, substituirão o relfilenode. Pode não ser o esperado, se você estiver tentando visualizá-lo simultaneamente sem usar o bloqueio apropriado.Algumas opções
Se você não precisar de confiabilidade, poderá usar as informações em
pg_stat_database
epg_stat_all_tables
. Isso pode indicar o horário da última redefinição de estatísticas e as atividades desde a última redefinição. Ele não informa quando foi a atividade mais recente, apenas que ocorreu desde a última redefinição de estatísticas e não há informações sobre o que aconteceu antes da redefinição dessas estatísticas. Portanto, é limitado, mas já está lá.Uma opção para fazer isso de forma confiável é usar um gatilho para atualizar uma tabela que contém os horários da última modificação para cada tabela. Esteja ciente de que isso serializará todas as gravações na tabela , destruindo a simultaneidade. Ele também adicionará um pouco de sobrecarga a todas as transações. Eu não recomendo.
Uma alternativa um pouco menos terrível é usar
LISTEN
eNOTIFY
. Tenha um processo de daemon externo conectado ao PostgreSQL eLISTEN
para eventos. UseON INSERT OR UPDATE OR DELETE
gatilhos para enviarNOTIFY
s quando uma tabela for alterada, com a tabela oid como carga útil de notificação. Eles são enviados quando a transação é confirmada. Seu daemon pode acumular notificações de alteração e gravá-las lentamente em uma tabela no banco de dados. Se o sistema travar, você perderá o registro das modificações mais recentes, mas tudo bem, você tratará todas as tabelas como modificadas apenas se estiver iniciando após uma falha.Para evitar os piores problemas de simultaneidade, você pode registrar os carimbos de data / hora da mudança usando um
before insert or update or delete or truncate on tablename for each statement execute
gatilho, generalizado para usar a relação oid como parâmetro. Isso inseriria um(relation_oid, timestamp)
par em uma tabela de registro de alterações. Você tem um processo auxiliar em uma conexão separada ou chamado periodicamente pelo seu aplicativo, agrega essa tabela para obter as informações mais recentes, mescla-a em uma tabela de resumo das alterações mais recentes e trunca a tabela de log. A única vantagem disso em relação à abordagem de ouvir / notificar é que ela não perde informações em caso de falha - mas é ainda menos eficiente também.Outra abordagem poderia ser a de escrever uma função de extensão C que usa (por exemplo)
ProcessUtility_hook
,ExecutorRun_hook
, etc à mesa alterações armadilha e estatísticas de atualização preguiçosamente. Não olhei para ver como isso seria prático; dê uma olhada nas várias opções _hook nas fontes.A melhor maneira seria corrigir o código estatístico para registrar essas informações e enviar um patch ao PostgreSQL para inclusão no núcleo. Não basta começar escrevendo código; aumente sua idéia em -hackers quando você pensar sobre isso o suficiente para ter uma maneira bem definida de fazê-lo (por exemplo, comece lendo o código, não apenas poste perguntando "como faço para ..."). Pode ser bom acrescentar os horários da última atualização
pg_stat_...
, mas você precisa convencer a comunidade de que vale a pena a sobrecarga ou fornecer uma maneira de torná-la opcionalmente rastreada - e você deve escrever o código para manter as estatísticas e envie um patch , porque apenas alguém que deseja esse recurso se incomodará com isso.Como eu faria isso
Se eu tivesse que fazer isso e não tivesse tempo de escrever um patch para fazê-lo corretamente, provavelmente usaria a abordagem de ouvir / notificar descrita acima.
Atualização para os carimbos de data e hora do commit do PostgreSQL 9.5
Atualização : O PostgreSQL 9.5 possui registros de data e hora . Se você os tiver ativado
postgresql.conf
(e também o fez no passado), poderá verificar o registro de data e hora da confirmação com a maior linhaxmin
para aproximar a hora da última modificação. É apenas uma aproximação, porque se as linhas mais recentes forem excluídas, elas não serão contadas.Além disso, os registros de registro de data e hora de confirmação são mantidos apenas por um tempo limitado. Portanto, se você quiser saber quando uma tabela que não é muito modificada é modificada, a resposta será efetivamente "não sei, há um tempo atrás".
fonte
O PostgreSQL 9.5 permite rastrear a confirmação da última modificação.
Verifique se o commit da faixa está ativado ou desativado usando a seguinte consulta
Se retornar "ON", vá para a etapa 3, modifique o postgresql.conf
mudança
para
Reinicie o sistema
Repita a etapa 1.
Use a seguinte consulta para rastrear a última confirmação
fonte
sudo service postgresql restart
.Sim, isso pode ser esperado - dados sobre alterações são armazenados no log de transações imediatamente. Os arquivos de dados podem ser atualizados com atraso no ponto de verificação_timeout (o padrão é 5 minutos). O Postgres não se mantém permanentemente a qualquer momento que você solicita.
fonte
Tenho quase o mesmo requisito para manter um cache de algumas tabelas em um aplicativo cliente. Digo quase , porque realmente não preciso saber a hora da última modificação, mas apenas para detectar se algo mudou desde a última vez em que o cache foi sincronizado.
Aqui está a minha abordagem:
Desde que você tenha uma coluna
id
(PK),created_on
(registro de data e hora de inserção) eupdated_on
(registro de data e hora de atualização, pode ser NULL) em todas as tabelas, você podeSe você concatenar isso e preceder o número de linhas, poderá criar uma tag de versão parecida
count:id#timestamp
e será exclusiva para todas as versões dos dados na tabela.fonte