Non esiste un record affidabile e autorevole dell'ora dell'ultima modifica di una tabella. L'uso del relfilenode è errato per molte ragioni:
Le scritture vengono inizialmente registrate nel registro testina di scrittura (WAL), quindi pigramente nell'heap (i file della tabella). Una volta che il record è in WAL, Pg non si affretta a scriverlo nell'heap e potrebbe non essere nemmeno scritto fino al successivo checkpoint di sistema;
Le tabelle più grandi hanno più fork, dovresti controllare tutte le fork e scegliere il timestamp più recente;
Un semplice SELECT
può generare attività di scrittura nella tabella sottostante a causa dell'impostazione del bit di suggerimento;
l'autovaccum e altri tipi di manutenzione che non modificano i dati visibili dell'utente modificano ancora i file delle relazioni;
alcune operazioni, come vaccum full
, sostituiranno il relfilenode. Potrebbe non essere quello che ti aspetti se stai cercando di guardarlo contemporaneamente senza prendere un blocco appropriato.
Alcune opzioni
Se non hai bisogno di affidabilità, puoi potenzialmente utilizzare le informazioni in pg_stat_database
e pg_stat_all_tables
. Questi possono dare il tempo dell'ultimo azzeramento statistiche, e le statistiche di attività fin dall'ultimo azzeramento statistiche. Non ti dice quando è stata l'attività più recente, solo che è stata dall'ultimo reset delle statistiche, e non ci sono informazioni su ciò che è accaduto prima del ripristino delle statistiche. Quindi è limitato, ma è già lì.
Un'opzione per farlo in modo affidabile è utilizzare un trigger per aggiornare una tabella contenente i tempi dell'ultima modifica per ogni tabella. Tieni presente che così facendo serializzerai tutte le scritture sul tavolo , distruggendo la concorrenza. Aggiungerà anche un bel po 'di sovraccarico a ogni transazione. Non lo consiglio.
Un'alternativa leggermente meno terribile è usare LISTEN
e NOTIFY
. Avere un processo daemon esterno connettersi a PostgreSQL e LISTEN
per eventi. Usa i ON INSERT OR UPDATE OR DELETE
trigger per inviare messaggi NOTIFY
quando una tabella cambia, con la tabella oid come payload di notifica. Questi vengono inviati quando viene eseguita la transazione. Il tuo demone può accumulare notifiche di modifica e scriverle pigramente su una tabella nel database. Se il sistema si arresta in modo anomalo, perdi il record delle modifiche più recenti, ma va bene, tratti solo tutte le tabelle come appena modificate se stai avviando dopo un arresto anomalo.
Per evitare il peggio dei problemi di concorrenza, è possibile invece registrare i timestamp di modifica utilizzando un before insert or update or delete or truncate on tablename for each statement execute
trigger, generalizzato per prendere l'oid di relazione come parametro. Ciò inserirà una (relation_oid, timestamp)
coppia in una tabella di registrazione delle modifiche. Quindi hai un processo di supporto su una connessione separata o chiamato periodicamente dalla tua app, aggrega quella tabella per le informazioni più recenti, uniscilo in una tabella di riepilogo delle modifiche più recenti e tronca la tabella di registro. L'unico vantaggio di questo rispetto all'approccio di ascolto / notifica è che non perde informazioni in caso di arresto anomalo, ma è anche meno efficiente.
Un altro approccio potrebbe essere quello di scrivere una funzione di estensione C che utilizzi (ad esempio) ProcessUtility_hook
, ExecutorRun_hook
, ecc per tabella cambia intrappolare e statistiche aggiornamento pigramente. Non ho cercato di vedere quanto sarebbe stato pratico; dai un'occhiata alle varie opzioni di _hook nelle fonti.
Il modo migliore sarebbe applicare una patch al codice statistico per registrare queste informazioni e inviare una patch a PostgreSQL per l'inclusione nel core. Non iniziare semplicemente scrivendo il codice; solleva la tua idea su -hackers una volta che ci hai pensato abbastanza per avere un modo ben definito di farlo (cioè iniziare leggendo il codice, non solo postare chiedendo "come posso ..."). Potrebbe essere utile aggiungere i tempi dell'ultimo aggiornamento pg_stat_...
, ma dovresti convincere la community che valeva il sovraccarico o fornire un modo per tenerlo tracciato facoltativamente - e dovresti scrivere il codice per mantenere le statistiche e inviare una patch , perché solo qualcuno che desidera questa funzione si preoccuperà di questo.
Come lo farei
Se dovessi farlo, e non avessi il tempo di scrivere una patch per farlo correttamente, probabilmente userei l'approccio di ascolto / notifica descritto sopra.
Aggiornamento per i timestamp di commit di PostgreSQL 9.5
Aggiornamento : PostgreSQL 9.5 ha i timestamp di commit . Se li hai abilitati in postgresql.conf
(e lo hai fatto anche in passato), puoi controllare il timestamp di commit per la riga con il massimo xmin
per approssimare l'ultima volta modificata. È solo un'approssimazione perché se le righe più recenti sono state eliminate non verranno conteggiate.
Inoltre, i record di data / ora del commit vengono conservati solo per un tempo limitato. Quindi, se vuoi dire quando una tabella che non è molto modificata viene modificata, la risposta sarà effettivamente "non so, poco fa".