Es gibt keine zuverlässige, autorisierende Aufzeichnung des letzten Änderungszeitpunkts einer Tabelle. Die Verwendung des relfilenode ist aus vielen Gründen falsch:
Schreibvorgänge werden zunächst im Schreibkopfprotokoll (WAL) und dann träge im Heap (den Tabellendateien) aufgezeichnet . Sobald der Datensatz in WAL ist, beeilt sich Pg nicht, ihn auf den Heap zu schreiben, und er wird möglicherweise erst beim nächsten Systemprüfpunkt geschrieben.
Größere Tabellen haben mehrere Gabeln. Sie müssen alle Gabeln überprüfen und den neuesten Zeitstempel auswählen.
Ein einfacher Befehl SELECT
kann aufgrund der Einstellung des Hinweisbits Schreibaktivitäten für die zugrunde liegende Tabelle generieren.
Autovaccum und andere Wartungsarbeiten, die die vom Benutzer angezeigten Daten nicht ändern, ändern weiterhin die Beziehungsdateien.
Einige Operationen, wie zum Beispiel vaccum full
, ersetzen den relfilenode. Es ist möglicherweise nicht der Ort, den Sie erwarten, wenn Sie versuchen, es gleichzeitig zu betrachten, ohne ein entsprechendes Schloss zu öffnen.
Ein paar Möglichkeiten
Wenn Sie keine Zuverlässigkeit benötigen, können Sie die Informationen möglicherweise in pg_stat_database
und verwenden pg_stat_all_tables
. Diese können Ihnen den Zeitpunkt des letzten Zurücksetzens der Statistiken und die Aktivitätsstatistik seit dem letzten Zurücksetzen der Statistiken anzeigen. Es gibt keine Auskunft darüber, wann die letzte Aktivität stattgefunden hat, nur darüber, dass sie seit dem letzten Zurücksetzen der Statistiken stattgefunden hat, und es gibt keine Informationen darüber, was vor dem Zurücksetzen der Statistiken geschehen ist. Also ist es begrenzt, aber es ist schon da.
Eine Möglichkeit, dies zuverlässig zu tun, besteht darin, einen Trigger zu verwenden, um eine Tabelle zu aktualisieren, die die zuletzt geänderten Zeiten für jede Tabelle enthält. Beachten Sie, dass dadurch alle Schreibvorgänge in die Tabelle serialisiert und die Parallelität zerstört wird. Außerdem wird jeder Transaktion ein gewisser Overhead hinzugefügt. Ich kann es nicht empfehlen.
Eine etwas weniger schreckliche Alternative ist die Verwendung von LISTEN
und NOTIFY
. Stellen Sie über einen externen Daemon-Prozess eine Verbindung zu PostgreSQL und LISTEN
zu Ereignissen her. Verwenden Sie ON INSERT OR UPDATE OR DELETE
Trigger, um NOTIFY
s zu senden, wenn sich eine Tabelle ändert, wobei die Tabelle oid als Benachrichtigungsnutzlast dient. Diese werden gesendet, wenn die Transaktion festgeschrieben wird. Ihr Daemon kann Änderungsbenachrichtigungen sammeln und diese träge in eine Tabelle in der Datenbank zurückschreiben. Wenn das System abstürzt, gehen die Aufzeichnungen der letzten Änderungen verloren, aber das ist in Ordnung. Wenn Sie nach einem Absturz starten, werden nur alle Tabellen als gerade geändert behandelt.
Um die schlimmsten Parallelitätsprobleme zu vermeiden, können Sie stattdessen die Änderungszeitstempel mithilfe eines before insert or update or delete or truncate on tablename for each statement execute
Triggers protokollieren , der verallgemeinert wird, um die Relation oid als Parameter zu verwenden. Dies würde ein (relation_oid, timestamp)
Paar in eine Änderungsprotokollierungstabelle einfügen . Sie haben dann einen Hilfsprozess auf einer separaten Verbindung oder werden regelmäßig von Ihrer App aufgerufen, aggregieren diese Tabelle für die neuesten Informationen, führen sie in einer Übersichtstabelle der neuesten Änderungen zusammen und kürzen die Protokolltabelle. Der einzige Vorteil gegenüber dem Listen / Notify-Ansatz besteht darin, dass beim Absturz keine Informationen verloren gehen - aber es ist auch noch weniger effizient.
Ein weiterer Ansatz könnte sein , eine C - Erweiterungsfunktion , dass Nutzungen (zB) zu schreiben ProcessUtility_hook
, ExecutorRun_hook
etc. zu stoppen Tabellenänderungen und lazily Update Statistiken. Ich habe nicht nachgesehen, wie praktisch dies sein würde. Schauen Sie sich die verschiedenen _hook-Optionen in den Quellen an.
Am besten patchen Sie den Statistikcode, um diese Informationen aufzuzeichnen, und senden Sie einen Patch an PostgreSQL, um ihn in den Core aufzunehmen. Beginnen Sie nicht einfach damit, Code zu schreiben. Wenden Sie sich an -hacker, wenn Sie genug darüber nachgedacht haben, um eine genau definierte Möglichkeit zu haben (dh lesen Sie zunächst den Code, und posten Sie nicht einfach die Frage, wie ich ...). Es mag nett sein, die zuletzt aktualisierten Zeiten hinzuzufügen pg_stat_...
, aber Sie müssten die Community davon überzeugen, dass sich der Aufwand gelohnt hat, oder eine Möglichkeit bieten, ihn optional zu verfolgen - und Sie müssten den Code schreiben, um die Statistiken und Daten zu speichern Reichen Sie einen Patch ein , denn nur wer dieses Feature möchte, wird sich darum kümmern.
Wie ich es machen würde
Wenn ich dies tun müsste und nicht die Zeit hätte, einen Patch zu schreiben, um es richtig zu machen, würde ich wahrscheinlich den oben beschriebenen Listen / Notify-Ansatz verwenden.
Update für PostgreSQL 9.5-Commit-Zeitstempel
Update : PostgreSQL 9.5 verfügt über festgeschriebene Zeitstempel . Wenn Sie sie aktiviert haben postgresql.conf
(und dies auch in der Vergangenheit getan haben), können Sie den Commit-Zeitstempel für die Zeile mit dem größten Wert überprüfen, um die letzte geänderte Zeit xmin
zu approximieren . Dies ist nur eine Annäherung, da die zuletzt gelöschten Zeilen nicht gezählt werden.
Commit-Zeitstempeldatensätze werden nur für eine begrenzte Zeit aufbewahrt. Wenn Sie also feststellen möchten, wann eine Tabelle, die nicht wesentlich geändert wurde, geändert wurde, lautet die Antwort "Keine Ahnung, vor einiger Zeit".