mysql - 与 SQL 的时区协调

标签 mysql go timezone timestamp-with-timezone

问题 1/3:

我有许多 MySQL 数据库要连接并希望确保跨查询的时间一致性。因此,例如,其中一台服务器当前处于 CDT 时区。

> select CURRENT_TIMESTAMP, @@system_time_zone, @@global.time_zone, @@session.time_zone;

+---------------------+--------------------+--------------------+---------------------+
| CURRENT_TIMESTAMP   | @@system_time_zone | @@global.time_zone | @@session.time_zone |
+---------------------+--------------------+--------------------+---------------------+
| 2019-05-31 09:44:45 | CDT                | SYSTEM             | SYSTEM              |
+---------------------+--------------------+--------------------+---------------------+

注意:我们现在处于 DST,因此是 CDT。我假设这会在 DST 之外时自动更改为 CST,对吗?

根据以上知识,我的 DSN 后缀看起来像这样:

...?parseTime=true&loc=America%2FChicago // i.e. 'America/Chicago' - maybe 'CST6CDT' would work too?

那么,go 中是否有一种编程方式可以将 3 字母代码 CDT 映射到更正式的时区名称,如 America/Chicago.

2/3:

上面是先有鸡还是先有蛋的场景:为了确定远程服务器的时区,需要连接/查询服务器;有了这些知识,DSN 参数可能会因将来的调用而改变。

事后是否可以更改 DSN 参数,或者是否需要创建一个全新的连接 sql.DB 连接池?

3/3:

您可能会问,为什么要检查时区是否已更改 - 它不是静态的吗?在负载平衡的数据库情况下应该做什么?理论上,两个副本可以位于不同的时区吗?

所有带有时间戳的列是否都应该用 SQL UNIX_TIMESTAMP() 包装起来以规范化数据并避免这种令人头疼的问题?

我也可以进入时间漂移,但我现在就到此为止。

最佳答案

1/3

go 使用 IANA 的 Time Zone Database具有精确的区域名称。 试图逆向工程 MySQL 如何从 (Linux) 主机确定本地时区格式并在 go 客户端中复制该逻辑 - 正如@MattJohnson 指出的那样 - 被证明是不可靠的。

2/3

database/sql.DB - 通过 Open(drv, DSN) 创建 - 将对所有连接使用相同的 DSN。虽然 sql.DB 旨在创建一次并多次使用 - 但事后无法更改 DSN - 因此需要创建一个品牌更改 DSN 时新建 sql.DB

3/3

因此,更好的策略似乎是利用 MySQL 将所有 datetime 值在传输到客户端之前从本地时区转换为 UTC 时区。这消除了在连接时通过 DSN 设置数据库(可能未知)时区的复杂性。

一个有前途的选择是设置连接的 session 时区:

  • SET @@session.time_zone = "+00:00";
  • 但是,这仅适用于当前 连接(在连接池中)。然而,go 客户端在任何给定时间都不知道他们可能正在使用哪个空闲连接。
  • 因此,为确保它始终有效,需要在所有查询 之前手动应用它。即使只有一个数据库连接在使用中 - 如果连接失败并且连接重试开始 - 之前的任何 session 状态都将丢失。

因此,将所有 datatime 列包装成一个转换函数,如下所示:

CONVERT_TZ(`STAMP_UPDATED`,@@session.time_zone,'+00:00')

确保时区计算在查询时完成,并且不会在连接重新连接等期间丢失。

所以现在 DSN 不再需要指定 loc - 因为 UTC 是默认值。事实上 DSN 只需要 ?parseTime=true 的后缀选项就可以让 datetime 被翻译成 go 的原生 time.Time

最后也是最重要的一点,这将适用于设置为任何时区的任何服务器。

H/T answer .

关于mysql - 与 SQL 的时区协调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56397882/

相关文章:

c# - 在 ASP.NET 中使用 MySql : Does closing a connection really release table locks?

sockets - 为什么连接读取返回缓冲区的长度,而不是真正发送?

pointers - Go的指针何时取消引用自己

go - 无效的接收器类型-可以与myType结构一起使用吗?

java - 将完整的 Java 日期(例如 8.00am 2013-06-19)转换为一个时间(即 8.00am 1970-01-01)

mysql "IN"条件与子查询

c# - 计算自签署之日起每年使用的服务

mysql - 防止 C 中的 SQL 注入(inject)

android - 我想从 GSM 网络获取时间

java - 从 Oracle 数据库中检索日期列时如何忽略 java 所做的 DST 调整?