2009-05-22 15 views
17

Ich arbeite mit einer PostgreSQL-Datenbank, die in Batches aktualisiert wird. Ich muss wissen, wann das letzte Mal, dass die Datenbank (oder eine Tabelle in der Datenbank) aktualisiert oder geändert wurde, beides tun wird.Wie finde ich das letzte Mal, dass eine PostgreSQL-Datenbank aktualisiert wurde?

Ich sah, dass jemand im PostgeSQL-Forum vorgeschlagen hatte, Protokollierung zu verwenden und Ihre Protokolle für die Zeit abzufragen. Dies wird für mich nicht funktionieren, da ich keine Kontrolle über die Client-Codebasis habe.

Antwort

22

Sie einen trigger schreiben kann jedes Mal, wenn ein insert/update ausgeführt wird auf eine bestimmte Tabelle. Die übliche Verwendung besteht darin, eine Spalte "created" oder "last_updated" der Zeile auf die aktuelle Zeit zu setzen, aber Sie können die Uhrzeit auch an einem zentralen Speicherort aktualisieren, wenn Sie die vorhandenen Tabellen nicht ändern möchten.

So zum Beispiel eine typische Art und Weise ist die folgende:

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(); 

Dann die letzte Aktualisierungszeit zu finden, müssen Sie aus jeder Tabelle der größten Sie verfolgen und nehmen „MAX (last_updated)“ wählen von denen, zB:

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 

Für Tabellen mit einem seriellen (oder in ähnlicher Weise generiert) Primärschlüssel, können Sie die sequenziellen Scan versuchen vermeiden Sie die neueste Update-Zeit zu finden, indem Sie den Primärschlüsselindex verwenden, oder Sie erstellen Indizes auf last_updated.

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

Beachten Sie, dass diese leicht zu falschen Ergebnissen bei der IDs nicht ganz sequenziellen geben kann sein, aber wie viel Genauigkeit benötigen Sie? (Bedenken Sie, dass Transaktionen dazu führen, dass Zeilen für Sie in einer anderen Reihenfolge angezeigt werden können.)

Ein alternativer Ansatz, um das Hinzufügen von "aktualisierten" Spalten zu jeder Tabelle zu vermeiden, ist eine zentrale Tabelle zum Speichern der Aktualisierung in Zeitstempel. zum Beispiel:

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(); 

Dies wird Ihnen mit einer Zeile für jede Tabelle Update eine Tabelle geben: Sie können dann nur tun:

SELECT MAX(updated) FROM update_log 

Um die letzte Aktualisierung der Zeit. (Sie können dies nach Tabelle aufteilen, wenn Sie möchten). Diese Tabelle wird natürlich immer weiter wachsen: Entweder einen Index für "aktualisiert" erstellen (was das neueste ziemlich schnell machen sollte) oder es regelmäßig abschneiden, wenn das zu Ihrem Anwendungsfall passt (zB eine exklusive Sperre für den Tisch, Holen Sie sich die letzte Aktualisierungszeit und kürzen Sie sie, wenn Sie regelmäßig überprüfen müssen, ob Änderungen vorgenommen wurden. Ein alternativer Ansatz - was wohl die Leute im Forum sein könnten - besteht darin, 'log_statement = mod' in der Datenbankkonfiguration (entweder global für den Cluster oder für die Datenbank oder den Benutzer, die Sie verfolgen müssen) zu setzen Anschließend werden alle Anweisungen, die die Datenbank ändern, in das Serverprotokoll geschrieben. Sie müssen dann etwas außerhalb der Datenbank schreiben, um das Serverprotokoll zu scannen, Tabellen herauszufiltern, an denen Sie nicht interessiert sind, usw.

4

Es sieht aus wie Sie pg_stat_database können Sie eine Transaktionsanzahl erhalten und prüfen, ob diese von einem Sicherungslauf zum nächsten ändert - siehe this dba.se answer und Kommentaren für mehr Details

0

Sie können eine gespeicherte Prozedur in einem „nicht vertrauenswürdigen schreiben Sprache "(zB plpythonu): Dies ermöglicht den Zugriff auf die Dateien im postgres" base "-Verzeichnis. Geben Sie die Größe dieser Dateien in der gespeicherten Prozedur zurück.

Aber das ist nur vage, da Vakuum diese Dateien und die Zeit ändern wird.

3

Ich mag Jacks Ansatz. Sie können die Tabellenstatistiken abfragen und die Anzahl der Einfügungen, Aktualisierungen, Löschungen kennen und so:

select n_tup_upd from pg_stat_user_tables where relname = 'YOUR_TABLE'; 

jedes Update die Zählung dieses Verfahren erhöhen sich um 1.

daran denkt, ist lebensfähig, wenn Sie eine haben einzelne DB. Mehrere Instanzen erfordern wahrscheinlich einen anderen Ansatz.