地理位置分散的服务器、PostgreSQL 和 JPA

Posted

技术标签:

【中文标题】地理位置分散的服务器、PostgreSQL 和 JPA【英文标题】:Geographically dispersed servers, PostgreSQL, and JPA 【发布时间】:2014-04-03 22:32:52 【问题描述】:

我的数据库服务器的 TIMEZONE 是 UTC。我在不同时区拥有与数据库交互的 Java 服务器。我天真地发现,如果我有一个 TIMESTAMP 字段,我真的无法从 Java 服务器的 JPA 代码中将它设置为 UTC。我想我天真地假设,如果 JDBC 总是发送带有 TZ 信息的日期,并且数据库服务器可以根据其时区适当地转换或转换。但不是。 :(

这就是问题所在。我可能有不同时区的 Java 服务器与这个数据库服务器交互。如果东海岸晚上 9 点和西海岸晚上 6 点发生什么事情,我希望这两个事件同时存储在数据库中。呃,对吧?

那么解决方案是什么,我想我可以将我所有的 Java 服务器都放在 UTC 中。但似乎应该有一个不那么笨拙的解决方案。我想我也可以在每笔交易上设置时区,但是啊。

我知道我会得到一些答案,说我应该只在数据库中存储 long,虽然我很欣赏这个答案的真实性,但我确实想在我的数据库表中保留 TIMEZONE 和 DATE 字段。所以我正在寻找其他类型的答案。谢谢。

【问题讨论】:

别忘了使用 NTP 同步时钟 我想你想要timestamp with time zone,而不是timestamp。如果您还希望保留时区/偏移量,则必须单独存储它——timestamp with time zone 类型的命名在这方面具有相当的欺骗性。感谢 SQL 标准。 如果 postgres 服务器在 UTC 中运行会有什么不同? 【参考方案1】:

解决方案是对这些瞬间使用 TIMESTAMPTZ 字段。诸如“用户何时创建”之类的内容永远不应与 TIMESTAMP 字段一起存储,因为默认情况下它不包含 TZ 信息。 JDBC 驱动程序非常随意地处理这些。例如,考虑以下情况:

假设您的 JVM 位于 America/Los_Angeles 区域,而您的数据库服务器位于 UTC。

然后创建下表:

 CREATE TABLE test (
   id   INTEGER,
   ts   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
   tswz TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
 );

如果您从 PSQL 发出:

 INSERT INTO test(id) values(1);

您将获得相同的“ts”和“tswz”值。两者都将是当前的 UTC 时间。但是,如果您使用 JDBC 驱动程序从 Java 执行 SAME EXACT 查询,则“ts”将是洛杉矶的当前时间,“tswz”将是 UTC 时间。

在这种情况下,我不知道驱动程序如何将 JVM 时区传送给服务器,因为我们在服务器上默认了该字段。他们说他们没有设置会话的时区,但他们必须。无论哪种方式,如果您使用 TIMESTAMPTZ 字段,那么无论它位于哪个时区,您都将从任何 JVM 获得相同的瞬间。

【讨论】:

以上是关于地理位置分散的服务器、PostgreSQL 和 JPA的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL(全文搜索)与 ElasticSearch

对于一个整数分散到数组之中的程序

地理分散启发式

地理服务器(VPS)连接到 PostgreSql(本地主机)

如何设置或更改PostgreSQL数据目录位置

我们如何在 PostgreSQL 中使用加密获取地理服务器中的原始数据