有没有办法设置“过期”时间,之后在 PostgreSQL 中自动删除数据条目?

Posted

技术标签:

【中文标题】有没有办法设置“过期”时间,之后在 PostgreSQL 中自动删除数据条目?【英文标题】:Is there a way to set an "expiry" time, after which a data entry is automatically deleted in PostgreSQL? 【发布时间】:2014-11-20 17:06:09 【问题描述】:

有什么方法可以为PostgreSQL 中的数据条目设置某种“到期”时间吗?我正在考虑类似于EXPIRE in Redis 的东西。

我不想存储时间戳,然后手动编写某种cron 作业来检查哪些条目已过期。

我正在尝试找出 PostgreSQL 中是否有任何可以提供此类功能的本机功能,或者为将来的版本请求此类功能是否有意义。

【问题讨论】:

postgresql 邮件列表中有讨论postgresql.org/message-id/… 我知道这不是一个真正的答案,所以我将它作为评论留下。 Postgres 不打算以这种方式用于临时数据。使用 Redis。当你需要的工具已经存在并且运行良好时,没有理由让 Postgres 成为你需要的工具。 【参考方案1】:

没有内置的过期功能,但如果您的目标是自动过期字段并将逻辑包含在您的数据库中(因此没有像 cron 作业这样的外部依赖),那么您总是可以编写一个触发器。下面是一个触发器示例,该触发器从表中删除时间戳早于 1 分钟的行。每当将新行插入同一个表时,它就会执行。您显然可以将触发器设置为在其他条件下执行,并根据需要在各种到期日期执行。我使用以下网站作为基础:http://www.the-art-of-web.com/sql/trigger-delete-old/

CREATE TABLE expire_table (
    timestamp timestamp NOT NULL DEFAULT NOW(),
    name TEXT NOT NULL
);

INSERT INTO expire_table (name) VALUES ('a');
INSERT INTO expire_table (name) VALUES ('b');
INSERT INTO expire_table (name) VALUES ('c');

select * from expire_table;
         timestamp          | name 
----------------------------+------
 2014-09-26 15:33:43.243356 | a
 2014-09-26 15:33:45.222202 | b
 2014-09-26 15:33:47.347131 | c
(3 rows)

CREATE FUNCTION expire_table_delete_old_rows() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  DELETE FROM expire_table WHERE timestamp < NOW() - INTERVAL '1 minute';
  RETURN NEW;
END;
$$;

CREATE TRIGGER expire_table_delete_old_rows_trigger
    AFTER INSERT ON expire_table
    EXECUTE PROCEDURE expire_table_delete_old_rows();

INSERT INTO expire_table (name) VALUES ('d');

select * from expire_table;
         timestamp          | name 
----------------------------+------
 2014-09-26 15:36:56.132596 | d
(1 row)

【讨论】:

@caeus 可能依赖于缓存和索引 -1。恕我直言,触发器不是您应该处理缺少的数据库功能的方式,因为触发器很难测试,难以维护,而且很麻烦。诚实并在您的应用程序中实现它。 :) 同意,我认为在每次插入时检查旧记录并删除它在性能方面真的很糟糕。例如,即使是执行需要 SQL 的 CRON 作业脚本之类的设置也不难。 如果有关于过期时间的索引,性能应该是相当不错的。 +1 到 Brett 的解决方案。对于像会话表这样的东西,您只希望用户拥有一个会话,我认为任何 INSERT 到会话表的触发器,以确保每个用户只有一个会话,是一个完全有效的用例.人们对某些东西是否“可测试”很着迷,因此他们编写了更复杂的解决方案(然后需要大量测试),而不是一些他们可以确信不会破坏的简单功能。【参考方案2】:

没有。没有这样的功能。

我看不出它比 (1) 只是“过期”时间戳或 (2) 时间戳 + cron-job/pgAgent 所做的更多。

这听起来不像是要添加到核心的一般功能。你可以很简单地编写一个 extension 来处理这种事情,或者从 cron-job 调用一个滴答声,或者可能是一个 background-worker 进程。

我在pgxn 上没有看到任何东西,所以大概还没有太多需求。

【讨论】:

我知道这个答案很旧,但 IMO 这是一个非常有用的功能,例如:docs.mongodb.com/manual/core/index-ttl 将这个特性添加到postgresql需要大量的工作,例如,外键创建需要不同的规则......

以上是关于有没有办法设置“过期”时间,之后在 PostgreSQL 中自动删除数据条目?的主要内容,如果未能解决你的问题,请参考以下文章

Redis设置过期时间

Redis过期策略

有没有办法为我在 ignitecache 中插入的不同元素设置不同的到期时间?

如何在 django 中设置会话永不过期

在windows上监视postgre 数据库 ,使用啥方式?

Redis的过期键机制