PostgreSQL的问题:’now’不断返回相同的旧值

PostgreSQL的问题:’now’不断返回相同的旧值,第1张

概述我有一个旧的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 inciden 我有一个旧的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+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 Values

Postgresql supports several special date/time input values for
convenIEnce,as shown in table 8-13. The values infinity 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 to transaction_timestamp().

和:

transaction_timestamp() is equivalent to CURRENT_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’不断返回相同的旧值所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1159021.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存