web-dev-qa-db-fra.com

Existe-t-il un moyen d'obtenir l'horodatage de la validation de transaction dans Postgres?

J'ai une fonctionnalité d'extraction de données qui, toutes les 5 secondes, récupère toutes les données de la table Postgres sur la base de la colonne modified_timestamp . Cela fonctionne de la manière suivante:

  1. SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp
  2. _some_persisted_timestamp = CURRENT_TIMESTAMP
  3. Traitement des données reçues de étape 1
  4. Dormez pendant 5s
  5. Allez à étape 1

horodatage modifié mis à jour avec le déclencheur (après toute mise à jour de ligne horodatage modifié devient CURRENT_TIMESTAMP). Cela a bien fonctionné jusqu'à ce que je remarque que CURRENT_TIMESTAMP dans Postgres est en fait l'horodatage de début de transaction et certaines des mises à jour sont perdues. Pourquoi sont-ils perdus? C'est assez simple - au moment où j'exécute la requête SELECT * FROM my_table WHERE modified_timestamp > _some_persisted_timestamp certaines des modifications ont déjà eu lieu, mais modified_timestamp est avant la mise à jour _ some_persisted_timestamp car la transaction est toujours en cours.

Ce problème pourrait être facilement résolu en affectant dans étape 2 horodatage lorsque la mise à jour devient visible pour d'autres transactions (horodatage de validation de transaction en d'autres termes) au lieu de CURRENT_TIMESTAMP ou clock_timestamp ().

J'ai lu la documentation, mais je n'ai rien trouvé concernant l'horodatage de la validation de transaction. Pourriez-vous gentiment suggérer smth?

Btw, je suis conscient de décodage logique et je sais que ce mécanisme convient mieux à mes besoins en théorie, mais il y a certains problèmes pratiques qui ne me permettent pas de l'utiliser.

4
bsiamionau

Ce problème pourrait être facilement résolu en affectant à l'étape 2 un horodatage lorsque la mise à jour devient visible pour d'autres transactions (horodatage de validation de transaction en d'autres termes) au lieu de CURRENT_TIMESTAMP ou clock_timestamp ().

C'est logiquement impossible. Postgres écrit de nouvelles versions de lignes avant il s'engage enfin à les rendre visibles. Il faudrait des capacités prophétiques pour écrire un horodatage futur encore inconnu au moment de la rédaction.

Cependant , vous pouvez obtenir des horodatages de validation à partir d'une source différente: depuis Postgres 9.5, il existe un paramètre GUC - track_commit_timestamp pour démarrer la journalisation des horodatages de validation à l'échelle mondiale.

Ensuite, vous pouvez obtenir des horodatages de validation avec la fonction utilitaire pg_xact_commit_timestamp(xid) . Votre requête pourrait ressembler à:

SELECT * FROM my_table t
WHERE   pg_xact_commit_timestamp(t.xmin) > _some_persisted_timestamp;

Vos étape 2 et étape 3 positions commerciales, et vous enregistrez l'horodatage de validation au lieu de CURRENT_TIMESTAMP - ou xmin à partir de toute ligne fraîchement mise à jour pour dériver l'horodatage de validation avec pg_xact_commit_timestamp() une fois de plus.

Plus:

À propos de xmin:

Mais je ne suis pas sûr de bien comprendre votre tâche. Vous avez peut-être besoin d'un outil de mise en file d'attente ou de traiter les lignes une par une, comme indiqué ici:

6
Erwin Brandstetter