J'essaie de voir quand ma table a été modifiée en vérifiant la date de modification de son fichier telle qu'elle est décrite dans cette réponse . Mais le résultat n'est pas toujours correct. La date de modification du fichier est mise à jour quelques minutes après la mise à jour de mon tableau. Est-ce comportement correct? PostgreSQL ™ stocke-t-il les modifications de table dans un cache, puis le vide sur le disque dur?
Alors, comment puis-je obtenir la date de dernière modification correcte d'un tableau (supposons que les modifications par aspiration automatique sont également acceptables)?
J'utilise PostgreSQL 9.2 sous Linux Centos 6.2 x64.
postgresql
écheveau
la source
la source
Réponses:
Il n’existe aucun enregistrement fiable et faisant autorité de la dernière heure modifiée d’une table. L'utilisation du relfilenode est fausse pour de nombreuses raisons:
Les écritures sont initialement enregistrées dans le journal de la tête d’écriture (WAL), puis par la suite dans le tas (les fichiers de la table). Une fois que l'enregistrement est dans WAL, Pg ne s'empresse pas de l'écrire dans le tas, et il est même possible qu'il ne soit pas écrit avant le prochain point de contrôle système.
Les tables plus grandes ont plusieurs fourchettes, vous devez vérifier toutes les fourches et choisir le dernier horodatage;
Un simple
SELECT
peut générer une activité d'écriture sur la table sous-jacente en raison de la définition de l'indice binaire;La maintenance automatique et les autres opérations de maintenance qui ne modifient pas les données visibles de l'utilisateur modifient toujours les fichiers de relation;
certaines opérations, par exemple
vaccum full
, remplaceront le relfilenode. Ce n'est peut-être pas ce à quoi vous vous attendez si vous essayez de l'examiner simultanément sans verrouiller de manière appropriée.Quelques options
Si vous n'avez pas besoin de fiabilité, vous pouvez potentiellement utiliser les informations dans
pg_stat_database
etpg_stat_all_tables
. Ceux-ci peuvent vous donner l'heure de la dernière réinitialisation des statistiques et des statistiques d'activité depuis la dernière réinitialisation des statistiques. Cela ne vous dit pas quand était la dernière activité, mais seulement depuis la dernière réinitialisation des statistiques, et il n'y a aucune information sur ce qui s'est passé avant cette réinitialisation. Donc, c'est limité, mais c'est déjà là.Une option pour le faire de manière fiable consiste à utiliser un déclencheur pour mettre à jour une table contenant les heures de dernière modification pour chaque table. Sachez que cela sérialisera toutes les écritures dans la table , détruisant ainsi la concurrence. Cela ajoutera également pas mal de frais généraux à chaque transaction. Je ne le recommande pas.
Une alternative légèrement moins terrible consiste à utiliser
LISTEN
etNOTIFY
. Demandez à un processus démon externe de se connecter à PostgreSQL etLISTEN
aux événements. Utilisez desON INSERT OR UPDATE OR DELETE
déclencheurs pour envoyer des messagesNOTIFY
quand une table est modifiée, avec la table oid comme charge utile de notification. Ceux-ci sont envoyés lorsque la transaction est validée. Votre démon peut accumuler des notifications de changement et les écrire paresseusement dans une table de la base de données. Si le système se bloque, vous perdez votre liste des modifications les plus récentes, mais ce n'est pas grave, vous ne faites que modifier toutes les tables comme si elles venaient d'être modifiées si vous démarrez après une panne.Pour éviter le pire des problèmes de simultanéité, vous pouvez plutôt enregistrer les horodatages de changement à l'aide d'un
before insert or update or delete or truncate on tablename for each statement execute
déclencheur, généralisé pour prendre la relation oid en tant que paramètre. Cela insérerait une(relation_oid, timestamp)
paire dans une table de journalisation des modifications. Vous avez ensuite un processus d'assistance sur une connexion distincte ou appelé périodiquement par votre application, agrégez cette table pour obtenir les informations les plus récentes, fusionnez-la dans un tableau récapitulatif des modifications les plus récentes et tronquez la table de journalisation. Le seul avantage de cette approche par rapport à l’écoute / notification est qu’elle ne perd pas d’informations sur les collisions - mais elle est aussi moins efficace.Une autre approche pourrait consister à écrire une fonction d'extension C qui utilise (par exemple)
ProcessUtility_hook
,ExecutorRun_hook
etc à des changements de table de pièges et paresseusement les statistiques de mise à jour. Je n'ai pas cherché à voir comment cela serait pratique; Jetez un coup d'œil aux différentes options de _hook dans les sources.Le meilleur moyen serait de corriger le code de statistiques pour enregistrer ces informations et de soumettre un correctif à PostgreSQL pour l'inclure dans le noyau. Ne commencez pas simplement par écrire du code; soulevez votre idée sur les hackers une fois que vous y avez suffisamment réfléchi pour avoir un moyen bien défini de le faire (c.-à-d. commencez par lire le code, ne vous contentez pas de demander "comment puis-je ..."). Il peut être intéressant d’ajouter à la dernière mise à jour
pg_stat_...
, mais vous devez convaincre la communauté que cela en vaut la peine ou fournir un moyen de le suivre éventuellement - et vous devez écrire le code pour conserver les statistiques et soumettez un correctif , car seul celui qui souhaite utiliser cette fonctionnalité s’ennuiera de cela.Comment je le ferais
Si je devais le faire et que je n'avais pas le temps d'écrire un correctif pour le faire correctement, j'utiliserais probablement l'approche d'écoute / notification décrite ci-dessus.
Mise à jour des horodatages de validation de PostgreSQL 9.5
Mise à jour : PostgreSQL 9.5 a des timestamps . Si vous les avez activé dans
postgresql.conf
(et l' ont fait dans le passé aussi), vous pouvez vérifier l'horodatage commettras de la ligne avec le plus grandxmin
pour se rapprocher de la dernière modification. Ce n'est qu'une approximation car si les lignes les plus récentes ont été supprimées, elles ne seront pas comptabilisées.De plus, les enregistrements d'horodatage de validation ne sont conservés que pendant un temps limité. Donc, si vous voulez savoir quand une table qui n'est pas modifiée beaucoup est modifiée, la réponse sera effectivement "ne sait pas, il y a quelque temps".
la source
PostgreSQL 9.5 nous permet de suivre le dernier commit modifié.
La validation de la piste de contrôle est activée ou désactivée à l'aide de la requête suivante
Si la réponse est "ON", passez à l'étape 3 sinon modifiez postgresql.conf
Changement
à
Redémarrez le système
Répétez l'étape 1.
Utilisez la requête suivante pour suivre le dernier commit
la source
sudo service postgresql restart
.Oui, on peut s’attendre à ce qu’il se comporte - les données sur les modifications sont immédiatement stockées dans le journal des transactions. Les fichiers de données peuvent être mis à jour avec un délai checkpoint_timeout (5 minutes par défaut). Postgres ne tient pas en permanence à tout moment que vous demandez.
la source
J'ai presque la même exigence pour conserver un cache de certaines tables sur une application cliente. Je dis presque , car je n'ai pas vraiment besoin de connaître l'heure de la dernière modification, mais seulement de détecter si quelque chose a changé depuis la dernière synchronisation du cache.
Voici mon approche:
Si vous avez une colonne
id
(PK),created_on
(horodatage d'insertion) etupdated_on
(timestamp de mise à jour, peut être NULL) sur chaque table, vous pouvezSi vous concattez cela et que vous ajoutez le nombre de lignes, vous pouvez créer une balise de version qui ressemble à celle
count:id#timestamp
-ci et qui sera unique pour chaque version des données de la table.la source