2009-05-22 8 views
17

Je travaille avec une base de données postgreSQL qui est mise à jour par lots. J'ai besoin de savoir quand la dernière fois que la base de données (ou une table dans la base de données) a été mise à jour ou modifiée, fera l'affaire.Comment trouver la dernière fois qu'une base de données PostgreSQL a été mise à jour?

J'ai vu que quelqu'un sur le forum postgeSQL avait suggéré d'utiliser la journalisation et d'interroger vos journaux pour l'instant. Cela ne fonctionnera pas pour moi car je n'ai aucun contrôle sur la base de code des clients.

Répondre

22

Vous pouvez écrire un trigger pour exécuter chaque fois qu'un insert/mise à jour est faite sur une table particulière. L'utilisation courante consiste à définir une colonne "créée" ou "last_updated" de la ligne à l'heure actuelle, mais vous pouvez également mettre à jour l'heure dans un emplacement central si vous ne souhaitez pas modifier les tables existantes.

Ainsi, par exemple d'une manière typique est la suivante:

CREATE FUNCTION stamp_updated() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$ 
BEGIN 
    NEW.last_updated := now(); 
    RETURN NEW; 
END 
$$; 
-- repeat for each table you need to track: 
ALTER TABLE sometable ADD COLUMN last_updated TIMESTAMP; 
CREATE TRIGGER sometable_stamp_updated 
    BEFORE INSERT OR UPDATE ON sometable 
    FOR EACH ROW EXECUTE PROCEDURE stamp_updated(); 

ensuite pour trouver la dernière fois mise à jour, vous devez sélectionner « MAX (LAST_UPDATED) » de chaque table que vous le suivi et prendre le plus grand de ceux-ci, par exemple:

SELECT MAX(max_last_updated) FROM (
    SELECT MAX(last_updated) AS max_last_updated FROM sometable 
    UNION ALL 
    SELECT MAX(last_updated) FROM someothertable 
) updates 

pour les tables avec une série (ou de la même généré) clé primaire, vous pouvez essayer d'éviter l'analyse séquentielle pour trouver la dernière heure de mise à jour en utilisant l'index de clé primaire, ou vous créer des indices sur last_updated.

-- get timestamp of row with highest id 
SELECT last_updated FROM sometable ORDER BY sometable_id DESC LIMIT 1 

Notez que cela peut donner des résultats un peu mal dans le cas d'ID ne pas être tout à fait séquentielle, mais combien précision avez-vous besoin? (Gardez à l'esprit que les transactions signifient que les lignes peuvent devenir visibles dans un ordre différent de leur création.)

Une autre approche pour éviter d'ajouter des colonnes 'mises à jour' à chaque table est d'avoir une table centrale pour stocker la mise à jour horodatages par exemple:.

CREATE TABLE update_log(table_name text PRIMARY KEY, updated timestamp NOT NULL DEFAULT now()); 
CREATE FUNCTION stamp_update_log() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$ 
BEGIN 
    INSERT INTO update_log(table_name) VALUES(TG_TABLE_NAME); 
    RETURN NEW; 
END 
$$; 
-- Repeat for each table you need to track: 
CREATE TRIGGER sometable_stamp_update_log 
AFTER INSERT OR UPDATE ON sometable 
FOR EACH STATEMENT EXECUTE stamp_update_log(); 

Cela vous donnera une table avec une ligne pour chaque mise à jour de la table: vous pouvez le faire:

SELECT MAX(updated) FROM update_log 

pour obtenir la dernière fois mise à jour. (Vous pourriez diviser cela par table si vous le vouliez). Cette table va bien sûr continuer à croître: soit créer un index sur 'mis à jour' (ce qui devrait rendre le dernier assez rapide) ou le tronquer périodiquement si cela correspond à votre cas d'utilisation, (par exemple prendre un verrou exclusif sur la table, obtenir la dernière heure de mise à jour, puis la tronquer si vous devez vérifier périodiquement si des modifications ont été apportées). Une approche alternative - qui pourrait être ce que les gens sur le forum signifiait - est de définir 'log_statement = mod' dans la configuration de la base de données (globalement pour le cluster, ou sur la base de données ou l'utilisateur que vous devez suivre) alors toutes les instructions qui modifient la base de données seront écrites dans le journal du serveur. Vous devrez ensuite écrire quelque chose en dehors de la base de données pour analyser le journal du serveur, filtrer les tables qui ne vous intéressent pas, etc.

4

Il semble que vous pouvez utiliser pg_stat_database pour obtenir un nombre de transactions et vérifier si cela change d'une course de sauvegarde à l'autre - voir this dba.se answer et commentaires pour plus de détails

0

Vous pouvez écrire une procédure stockée dans un « non approuvé langue "(par exemple plpythonu): Cela permet d'accéder aux fichiers dans le répertoire" base "de postgres. Renvoyer le plus grand temps de ces fichiers dans la procédure stockée.

Mais ce n'est que vague, puisque le vide va changer ces fichiers et le mtime.

3

J'aime l'approche de Jack. Vous pouvez interroger les statistiques de table et de connaître le nombre d'insertions, mises à jour, suppressions et ainsi:

select n_tup_upd from pg_stat_user_tables where relname = 'YOUR_TABLE'; 

chaque mise à jour augmente le nombre de 1.

nue à l'esprit cette méthode est viable lorsque vous avez un DB unique. plusieurs instances nécessiteront probablement une approche différente.

Questions connexes