Question

Je veux vérifier les tables ont été mis à jour au cours d'une période donnée, par exemple dans l'ordre décroissant de temps d'accès par table.

Comment puis-je obtenir pour PostgreSQL?

Était-ce utile?

La solution

Vous pouvez obtenir des informations sur la dernière modification apportée à une table avec xmin , par exemple:

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

Mais vous devez être conscient de nombreuses mises en garde, y compris modulo et et wraparound XID congelés .

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

méthode:

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

nettoyage:

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

Autres conseils

Une installation PostgreSQL vanille ne se connecte pas accès aux tables.

Si vous avez besoin que vous devez mettre en œuvre vous-même. J'utiliser des déclencheurs pour cela. J'utilise une configuration comme celui-ci pour plusieurs de mes tableaux. Ajouter une colonne nommée log_up aux tables que je veux suivre les mises à jour pour:

log_up timestamptz DEFAULT current_timestamp;

Utilisation timestamptz (timestamp with time zone) qui fonctionne sur plusieurs fuseaux horaires:

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

Il y a deux liés paramètres d'enregistrement vous pouvez être intéressé par de plus. Comme log_connections ou log_statement.

Mise à jour: Voir également "horodatages" ajouté dans Postgres 9.5 :

déclencheur Ajouter à toutes les tables

Vous pouvez créer un script pour toutes les tables qui existent actuellement en interrogeant le catalogue de base de données. Par exemple, pour générer les instructions DDL pour toutes les tables du schéma 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

Renvoie:

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

Bien sûr, ils ont tous besoin d'avoir une log_up de colonne de type timestamptz premier. Vous pouvez créer un script DDL pour ajouter la colonne à toutes les tables de la même manière.


Se connecter uniquement dernière UPDATE par table

Si vous ne souhaitez que la dernière UPDATE par table, une solution plus simple fera. Voici une démo comment garder une trace dans une table centralisée:

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

Trigger. Consultez le manuel sur les variables spéciales J'utilise:

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;

Tableau factice pour le test:

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

Entrée ligne pour la table dans la table de journal:

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

Trigger. Notez que j'utilise un AFTER de déclenchement de FOR EACH STATEMENT (moins cher). Plus dans le manuel ici.

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

Test:

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

Voilá:

SELECT * FROM lastup;

ou , si vous voulez exclure les mises à jour vide (rien changé), mais à un coût plus élevé car plusieurs lignes mises à jour déclenchent des mises à jour du journal:

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

créer des déclencheurs pour toutes les tables que vous souhaitez inclure dans ce régime, utiliser un même script de création de LDD comme ci-dessus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top