PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come faccio a trovare l'ultima volta che un database PostgreSQL è stato aggiornato?

Puoi scrivere un trigger da eseguire ogni volta che viene eseguito un inserimento/aggiornamento su una tabella particolare. L'uso comune è impostare una colonna "created" o "last_updated" della riga sull'ora corrente, ma puoi anche aggiornare l'ora in una posizione centrale se non desideri modificare le tabelle esistenti.

Quindi per esempio un modo tipico è il seguente:

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

Quindi, per trovare l'ora dell'ultimo aggiornamento, devi selezionare "MAX(last_updated)" da ogni tabella che stai monitorando e prendere la più grande di quelle, ad esempio:

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

Per le tabelle con una chiave primaria seriale (o generata in modo simile), puoi provare a evitare la scansione sequenziale per trovare l'ora di aggiornamento più recente utilizzando l'indice della chiave primaria oppure puoi creare indici su last_updated.

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

Nota che questo può dare risultati leggermente errati nel caso in cui gli ID non siano abbastanza sequenziali, ma di quanta precisione hai bisogno? (Ricorda che le transazioni significano che le righe possono essere visibili a te in un ordine diverso da quello in cui sono state create.)

Un approccio alternativo per evitare di aggiungere colonne "aggiornate" a ciascuna tabella consiste nell'avere una tabella centrale in cui archiviare i timestamp di aggiornamento. Ad esempio:

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

Questo ti darà una tabella con una riga per ogni aggiornamento della tabella:puoi quindi fare semplicemente:

SELECT MAX(updated) FROM update_log

Per ottenere l'ora dell'ultimo aggiornamento. (Potresti dividerlo per tabella se lo desideri). Questa tabella ovviamente continuerà a crescere:crea un indice su "aggiornato" (che dovrebbe rendere l'ultimo abbastanza veloce) o troncalo periodicamente se si adatta al tuo caso d'uso, (ad esempio prendi un blocco esclusivo sul tavolo, ottenere l'ultima ora di aggiornamento, quindi troncarla se è necessario controllare periodicamente se sono state apportate modifiche).

Un approccio alternativo, che potrebbe essere ciò che intendevano le persone del forum, consiste nell'impostare 'log_statement =mod' nella configurazione del database (o a livello globale per il cluster, o sul database o sull'utente che devi tenere traccia) e quindi tutte le istruzioni che modificare il database verrà scritto nel registro del server. Dovrai quindi scrivere qualcosa al di fuori del database per scansionare il registro del server, filtrare le tabelle che non ti interessano, ecc.