Domanda

Voglio controllare che le tabelle sono state aggiornate nel corso di un determinato periodo, per esempio in ordine di tempo di accesso per ogni tabella decrescente.

Come posso ottenere che per PostgreSQL?

È stato utile?

Soluzione

È possibile ottenere alcune informazioni circa l'ultima modifica a una tabella con xmin , ad esempio:

select max(xmin::text::bigint) from t;

Ma è necessario essere consapevoli di molti avvertimenti compreso modulo e avvolgente e XID congelati .

Testbed:

set role dba;
create role stack;
grant stack to dba;
create schema authorization stack;
set role stack;
--
create or replace function f(p_schema in text, p_table in text) 
                  returns integer language plpgsql immutable as $$
declare
  n integer;
begin
  execute 'select max(xmin::text::bigint) from '||p_schema||'.'||p_table into n;
  return n;
end;$$;
--
create table foo as select generate_series(1, 100) as id;
create table bar as select generate_series(1, 100) as id;
create table baz as select generate_series(1, 100) as id;
--

Metodo:

select table_name, f(table_schema, table_name)
from information_schema.tables
where table_schema='stack'
order by 2 desc;
/*
 table_name |   f
------------+--------
 baz        | 784657
 bar        | 784656
 foo        | 784655
*/
--
update foo set id=id+1 where id=100;
--
select table_name, f(table_schema, table_name)
from information_schema.tables
where table_schema='stack'
order by 2 desc;
/*
 table_name |   f
------------+--------
 foo        | 784658
 baz        | 784657
 bar        | 784656
*/

cleanup:

drop schema stack cascade;
set role dba;
drop role stack;

Altri suggerimenti

installazione

Un vaniglia PostgreSQL non registra l'accesso alle tabelle.

Se avete bisogno di avere per la sua attuazione da soli. Vorrei utilizzare i trigger per questo. Io uso una configurazione simile per molti dei miei tavoli. Aggiungo una colonna denominata log_up alle tabelle voglio tenere traccia degli aggiornamenti per:

log_up timestamptz DEFAULT current_timestamp;

Usa timestamptz (timestamp with time zone) che opera attraverso i fusi orari:

funzione trigger:

CREATE OR REPLACE FUNCTION trg_log_up()
  RETURNS trigger AS
$func$
BEGIN
   NEW.log_up := current_timestamp;
   RETURN NEW;
END;
$func$
  LANGUAGE plpgsql VOLATILE;

trigger:

CREATE TRIGGER log_up
BEFORE UPDATE ON tbl
FOR EACH ROW EXECUTE PROCEDURE trg_log_up();

Ci sono un paio di relativi parametri di registrazione si può essere interessati in aggiunta. Come log_connections o log_statement.

Aggiornamento: Considera anche "commit timestamp" aggiunto in Postgres 9.5 :

Add grilletto per tutte le tabelle

È possibile creare uno script per tutte le tabelle attualmente esistenti interrogando il catalogo di database. Per esempio per generare le istruzioni DDL per tutte le tabelle del public schema:

SELECT string_agg(format('CREATE TRIGGER log_up BEFORE UPDATE ON %s '
                         'FOR EACH ROW EXECUTE PROCEDURE trg_log_up();'
                        , c.oid::regclass), E'\n')
FROM   pg_namespace n
JOIN   pg_class     c ON c.relnamespace = n.oid
WHERE  n.nspname = 'public';
-- AND c.relname ~~* '%tbl%' -- to filter tables by name

Returns:

CREATE TRIGGER log_up BEFORE UPDATE ON tbl1 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
CREATE TRIGGER log_up BEFORE UPDATE ON tbl2 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
CREATE TRIGGER log_up BEFORE UPDATE ON tbl3 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
...

Naturalmente, tutti hanno bisogno di avere un log_up colonna di tipo timestamptz prima. È possibile creare uno script DDL per aggiungere la colonna a tutte le tabelle in un modo simile.


solo Log ultima UPDATE per tabella

Se si è interessati solo nell'ultimo UPDATE per tavolo, una soluzione più semplice farà. Ecco una demo di come tenere traccia in una tabella centralizzata:

CREATE TABLE lastup (
  schema_name text
, tbl_name text
, ts timestamptz
, PRIMARY KEY (schema_name, tbl_name)
);

trigger. Consultare il manuale sulle variabili speciali io uso:

CREATE OR REPLACE FUNCTION trg_lastup()
  RETURNS trigger AS
$func$
BEGIN
   UPDATE lastup
   SET    ts = current_timestamp
   WHERE  schema_name = TG_TABLE_SCHEMA
   AND    tbl_name    = TG_TABLE_NAME;

   RETURN NULL;   -- For AFTER trigger irrelevant
END
$func$  LANGUAGE plpgsql;

Tavolo Dummy per il test:

CREATE TABLE dummy (id int);
INSERT INTO dummy VALUES (1), (2), (3);

Inserisci riga per la tabella nella tabella di log:

INSERT INTO lastup(schema_name, tbl_name) VALUES ('public', 'dummy');

trigger. Si noti che io uso un AFTER FOR EACH STATEMENT grilletto (più economico). Più nel manuale qui.

CREATE TRIGGER log_up
AFTER UPDATE ON dummy
FOR EACH STATEMENT EXECUTE PROCEDURE trg_lastup();

Prova:

UPDATE dummy
SET    id = id + 5
WHERE  id < 3;

voilà:

SELECT * FROM lastup;

o , se si desidera escludere aggiornamenti vuote (nulla è cambiato), ma ad un costo più elevato perché più aggiornato righe innescare più aggiornamenti di registro:

CREATE OR REPLACE FUNCTION trg_lastup()
  RETURNS trigger AS
$func$
BEGIN
   IF OLD IS DISTINCT FROM NEW THEN  -- check for changes
      UPDATE lastup
      SET    ts = current_timestamp
      WHERE  schema_name = TG_TABLE_SCHEMA
      AND    tbl_name    = TG_TABLE_NAME;
   END IF;

   RETURN NULL;  -- For AFTER trigger!
END;
$func$  LANGUAGE plpgsql;

CREATE TRIGGER log_up
AFTER UPDATE ON dummy
FOR EACH ROW EXECUTE PROCEDURE trg_lastup();  -- per ROW instead of STATEMENT

creare i trigger per tutte le tabelle che si desidera includere in questo regime, utilizzare uno script di creazione DDL simile come sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top