PostgreSQL的问题:’now’不断返回相同的旧值
我有一个旧的Web应用程序,相关的当前堆栈是:
Java 8,Tomcat 7,Apache Commons DBCP 2.1,Spring 2.5(用于事务),iBatis,PostgreSQL 9.2和postgresql-9.4.1208.jar
部分代码在事件表中插入新记录,其中字段begin_date(带时区的时间戳(3))是创建时间戳,现在填充: insert into incidents (....,begin_date,) values (...,'now' ....) 所有这些都是通过iBatis执行的,通过Spring以编程方式管理的事务,通过DBCP池获取的连接. webapp(实际上是一对,客户端和后台,共享大部分代码和jar)多年来一直在工作. 最近,也许在一些库更新和重组之后(似乎没什么重要的),我一直在经历(间歇性,难以重现)一些令人讨厌的问题:现在似乎冻结了,它开始返回相同的“旧”值.然后,许多记录显示具有相同的创建时间戳,小时或几天前: db=# select 'now'::timestamptz; timestamp ------------------------- 2016-06-10 21:59:03.637+00 db=# select rid,begin_date from incidents order by rid desc limit 6; rid | begin_date -------+---------------------------- 85059 | 2016-06-08 00:11:06.503+00 85058 | 2016-06-08 00:11:06.503+00 85057 | 2016-06-08 00:11:06.503+00 85056 | 2016-06-08 00:11:06.503+00 85055 | 2016-06-08 00:11:06.503+00 85054 | 2016-06-08 00:11:06.503+00 (以上所有记录实际上是在2016-06-10 21:50之前的几分钟创建的) 怎么会发生这种情况?它可能是与事务和/或连接池有关的一些问题,但我无法弄清楚是什么. 首先,我可以插入一条新记录(通过webapp),并使用psql控制台,我看到它是用相同的begin_date编写的(如果事务是uncommited,我不应该看到新记录,我有默认值序列化水平). 此外,pg_stat_activity视图仅显示空闲连接. 任何线索? 解决方法
“现在”有常量(特殊时间戳值).
现在有了函数(). 你自由地混合它们这一事实表明你并没有意识到最重要的区别. The manual:
大胆强调我的. 并且(就像你已经提到的那样),但引用了the manual:
和:
还有更多,阅读整章. 现在(没有双关语),因为您使用特殊值而不是函数,所以您使用预准备语句获得了不同的(意外的)行为. 考虑这个演示: test=# BEGIN; BEGIN test=# PREPARE foo AS test-# SELECT timestamptz 'now' AS now_constant,now() AS now_function; PREPARE test=# EXECUTE foo; now_constant | now_function -------------------------------+------------------------------- 2016-06-11 03:09:05.622783+02 | 2016-06-11 03:09:05.622783+02 -- identical (1 row) test=# commit; COMMIT test=# EXECUTE foo; now_constant | now_function -------------------------------+------------------------------ 2016-06-11 03:09:05.622783+02 | 2016-06-11 03:10:00.92488+02 -- different! (1 row) 当您在同一个事务中运行时,’now’和now()会生成相同的值.但是,准备好的语句旨在持续会话期间(可能跨越许多事务).下次执行预准备语句时,您将看到不同之处. 换句话说:’now’实现“早期绑定”,而now()实现“后期绑定”. 您可能已经引入了预准备语句和/或连接池(可以在较长时间内保留准备好的语句) – 这两者通常都是好主意.但是你的INSERT中隐藏的问题现在开始了. 您看到的“空闲连接”表示同样多:连接保持打开状态,保留准备好的语句. 简而言之:立即使用(). 或者,将列默认值begin_date设置为now()(不是’now’!),并且不要在INSERT中提及该列.您的“创建时间戳”会自动保存. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |