部分代码在事件表中插入新记录,其中字段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之前的几分钟创建的)
怎么会发生这种情况?它可能是与事务和/或连接池有关的一些问题,但我无法弄清楚是什么.
我知道’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 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; 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中提及该列.您的“创建时间戳”会自动保存.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。