You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postgres 10:在不可变函数中伪造now()是否安全?

在Postgres 10的不可变函数中伪造now()是否安全?

嘿,针对你的这个疑问,我来拆解下这里面的安全性和风险点——毕竟你做的是给皮划艇爱好者提供水位降雨信息的服务,数据准确性和查询稳定性肯定是核心对吧?

结论先行:这么做并不安全,而且对你的场景风险很大

为什么违背Postgres的设计逻辑?

Postgres对函数的稳定性有明确的分级规则:

  • IMMUTABLE(不可变)函数要求相同输入必须返回完全相同的结果,绝对不能依赖任何可变的外部状态(比如当前时间、数据库数据变化)。
  • now()属于VOLATILE(易变)函数,每次调用结果都不同,把它塞进不可变函数里,直接打破了不可变函数的核心约定。

带来的直接风险有两个:

  1. 查询结果不准确:Postgres会缓存不可变函数的计算结果,一旦你伪造now(),后续查询可能复用几小时甚至几天前的旧时间值,导致你查水位数据时漏掉最新的15分钟上报读数,这对依赖实时数据的皮划艇用户来说是致命的。
  2. 分区剪枝失效:你迁移到Linode自建服务器就是为了用范围分区提速,要是函数稳定性被破坏,Postgres规划器没法正确判断该扫描哪些2周分片,直接回到全表扫描的慢速度,分区的优势完全浪费。

有没有“相对安全”的例外?

说实话,几乎没有适合你场景的例外。如果是一次性的临时脚本查询,而且你明确知道不会复用查询规划,可能暂时不会出问题,但对你这种持续接收数据、需要稳定查询的服务来说,这种情况完全不适用。

针对你的水位数据场景,更安全的替代方案

既然你是按2周分片存储水位计读数,推荐这两种更稳妥的方式:

  • 直接在查询中写时间逻辑:比如查最近2周的数据,直接用WHERE reading_time >= now() - interval '2 weeks',这种写法清晰直白,Postgres能正确识别时间范围,正常触发分区剪枝,查询速度有保障。
  • 用STABLE函数封装逻辑:如果必须把时间判断封装成函数,把函数的稳定性设为STABLE而非IMMUTABLE。STABLE函数在同一个查询内结果不变,但不同查询会重新计算now(),既满足你封装逻辑的需求,又不会破坏规划器的判断,分区剪枝也能正常工作。

内容的提问来源于stack exchange,提问作者Debaser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:59:58