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
et pg_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
et NOTIFY
. Demandez à un processus démon externe de se connecter à PostgreSQL et LISTEN
aux événements. Utilisez des ON INSERT OR UPDATE OR DELETE
déclencheurs pour envoyer des messages NOTIFY
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 grand xmin
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".