Frage

Ich möchte überprüfen, welche Tabellen während eines bestimmten Zeitraums aktualisiert wurden, beispielsweise in der absteigenden Reihenfolge der Zugriffszeit pro Tabelle.

Wie kann ich das für Postgresql bekommen?

War es hilfreich?

Lösung

Sie können einige Informationen über die letzte Änderung zu einer Tabelle mit erhalten xmin, z.B:

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

Aber Sie müssen sich bewusst sein von vielen Einschränkungen einschließlich Modulo und Wrack und Gefrorene Xids.

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

Methode:

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
*/

Aufräumen:

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

Andere Tipps

Eine Vanille -Postgresql -Installation protokolliert keinen Zugriff auf Tabellen.

Wenn Sie brauchen, müssen Sie es selbst implementieren. Ich würde dafür Trigger verwenden. Ich benutze ein solches Setup für viele meiner Tische. Ich füge eine Spalte mit dem Namen hinzu log_up Zu Tabellen möchte ich Updates verfolgen für:

log_up timestamptz DEFAULT current_timestamp;

Verwenden timestamptz (timestamp with time zone) die in Zeitzonen in allen Zeitzonen funktioniert:

Auslöserfunktion:

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

Abzug:

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

Es gibt ein paar verwandte Protokollierungsparameter Möglicherweise interessieren Sie sich zusätzlich. Wie log_connections oder log_statement.

Aktualisieren:Auch bedenken "Zeitstempel begehen" in Postgres hinzugefügt 9.5:

Fügen Sie allen Tabellen Trigger hinzu

Sie können ein Skript für alle aktuell vorhandenen Tabellen erstellen, indem Sie den Datenbankkatalog abfragen. Zum Beispiel, um die DDL -Anweisungen für alle Tabellen im Schema zu generieren public:

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

Kehrt zurück:

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

Natürlich müssen sie alle eine Spalte haben log_up vom Typ timestamptz Erste. Sie können ein DDL -Skript erstellen, um die Spalte auf ähnliche Weise zu allen Tabellen hinzuzufügen.


Nur zuletzt protokollieren UPDATE pro Tabelle

Wenn Sie nur an der letzten interessiert sind UPDATE pro Tabelle ist eine einfachere Lösung. Hier ist eine Demo, wie man in einer zentralen Tabelle den Überblick behält:

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

Abzug. Konsultieren Sie die Handbuch zu den besonderen Variablen Ich benutze:

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;

Dummy -Tisch zum Testen:

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

Geben Sie die Zeile für die Tabelle in der Protokolltabelle ein:

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

Abzug. Beachten Sie, dass ich eine verwende AFTER Abzug FOR EACH STATEMENT (billiger). Mehr im Handbuch hier.

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

Prüfen:

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

Voilá:

SELECT * FROM lastup;

Oder, wenn Sie wollen leere Updates ausschließen (Nichts hat sich geändert), aber zu höheren Kosten, da mehrere aktualisierte Zeilen mehrere Protokoll -Updates auslösen:

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

Zu Trigger erstellen Verwenden Sie für alle Tabellen, die Sie in dieses Regime aufnehmen möchten, ein ähnliches DDL -Erstellungsskript wie oben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top