20

我正在使用一个批量更新的 postgreSQL 数据库。我需要知道上次更新或修改数据库(或数据库中的表)的时间,两者都可以。

我看到 postgeSQL 论坛上有人建议使用日志记录并查询您的日志。这对我不起作用,因为我无法控制客户端代码库。

4

5 回答 5

29

您可以编写一个触发器以在每次对特定表进行插入/更新时运行。常见的用法是将行的“created”或“last_updated”列设置为当前时间,但如果您不想更改现有表,也可以在中心位置更新时间。

因此,例如一种典型的方式是以下一种:

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

然后要找到最后更新时间,您需要从您正在跟踪的每个表中选择“MAX(last_updated)”并取其中最大的一个,例如:

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

对于具有串行(或类似生成)主键的表,您可以尝试通过使用主键索引来避免顺序扫描以查找最新更新时间,或者在 last_updated 上创建索引。

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

请注意,在 ID 不是很连续的情况下,这可能会给出稍微错误的结果,但是您需要多少准确度?(请记住,事务意味着行可以以与创建行不同的顺序对您可见。)

避免向每个表添加“更新”列的另一种方法是使用一个中央表来存储更新时间戳。例如:

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

这将为您提供一个表,其中每个表更新都有一行:然后您可以这样做:

SELECT MAX(updated) FROM update_log

获取最后更新时间。(如果你愿意,你可以按表分开)。该表当然会继续增长:要么在“更新”上创建一个索引(这应该可以非常快地获得最新的索引),或者如果适合您的用例,则定期截断它,(例如,在表上获取排他锁,获取最新的更新时间,如果需要定期检查是否进行了更改,则将其截断)。

另一种方法(可能是论坛上的人的意思)是在数据库配置中设置“log_statement = mod”(无论是全局的集群,还是您需要跟踪的数据库或用户),然后所有语句修改数据库将写入服务器日志。然后你需要在数据库之外写一些东西来扫描服务器日志,过滤掉你不感兴趣的表,等等。

于 2009-05-22T19:02:13.153 回答
6

看起来您可以pg_stat_database用来获取事务计数并检查这是否从一个备份运行更改为下一个备份运行 - 有关更多详细信息,请参阅此 dba.se 答案和评论

于 2011-08-27T21:24:13.857 回答
2

请参阅以下文章:

MySQL 与 PostgreSQL:向表中添加“上次修改时间”列 http://www.pointbeing.net/weblog/2008/03/mysql-versus-postgresql-adding-a-last-modified-column-to-a -table.html

于 2009-05-22T18:19:54.443 回答
2

我喜欢杰克的做法。您可以查询表统计信息并了解插入、更新、删除等的数量:

select n_tup_upd from pg_stat_user_tables  where relname = 'YOUR_TABLE';

每次更新都会将计数增加 1。

请记住,当您只有一个数据库时,这种方法是可行的。多个实例可能需要不同的方法。

于 2015-04-30T12:17:52.107 回答
0

您可以用“不受信任的语言”(例如 plpythonu)编写存储过程:这允许访问 postgres“base”目录中的文件。返回存储过程中这些文件的最大 mtime。

但这只是模糊的,因为vacuum会改变这些文件和mtime。

于 2013-01-09T15:05:52.263 回答