部分代码在事件表中插入新记录,其中字段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+00db=# 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之前的几分钟创建的)
怎么会发生这种情况?它可能是与事务和/或连接池有关的一些问题,但我无法弄清楚是什么.
我知道’now()‘是transaction_timestamp()的别名,它返回事务开始时的时间.这表明交易没有正确关闭,上面的记录插入(无意中)写在一个长期交易中.但这对我来说相当不可思议.
首先,我可以插入一条新记录(通过webapp),并使用psql控制台,我看到它是用相同的begin_date编写的(如果事务是uncommited,我不应该看到新记录,我有默认值序列化水平).
此外,pg_stat_activity视图仅显示空闲连接.
任何线索?
解决方法 “现在”有常量(特殊时间戳值).现在有了函数().
你自由地混合它们这一事实表明你并没有意识到最重要的区别. The manual:
Special ValuesPostgresql supports several special date/time input values for
convenIEnce,as shown in table 8-13. The valuesinfinity
and-infinity
are specially represented insIDe the system and will be displayed
unchanged; but the others are simply notational shorthands that will
be converted to ordinary date/time values when read. (In particular,Now
and related strings are converted to a specific time value as soon
as they are read.) All of these values need to be enclosed in single
quotes when used as constants in sql commands.
大胆强调我的.
并且(就像你已经提到的那样),但引用了the manual:
Now()
is a Traditional Postgresql equivalent totransaction_timestamp()
.
和:
transaction_timestamp()
is equivalent toCURRENT_TIMESTAMP
还有更多,阅读整章.
现在(没有双关语),因为您使用特殊值而不是函数,所以您使用预准备语句获得了不同的(意外的)行为.
考虑这个演示:
test=# BEGIN;BEGINtest=# PREPARE foo AStest-# SELECT timestamptz 'Now' AS Now_constant,Now() AS Now_function;PREPAREtest=# 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;COMMITtest=# 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中提及该列.您的“创建时间戳”会自动保存.
总结以上是内存溢出为你收集整理的PostgreSQL的问题:’now’不断返回相同的旧值全部内容,希望文章能够帮你解决PostgreSQL的问题:’now’不断返回相同的旧值所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)