我有多个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
。我假设,它将在CST
之外自动更改为DST
,对吧?
基于上述知识,我的DSN
后缀看起来像这样:
...?parseTime=true&loc=America%2FChicago // i.e. 'America/Chicago' - maybe 'CST6CDT' would work too?
因此,go
中是否有一种编程方式可以将3字母代码CDT
映射到更正式的时区名称,例如America/Chicago
。
上面介绍了一个鸡/蛋的情况:为了确定远程服务器的时区,需要连接/查询服务器;知道这一点后,DSN参数可能会为将来的调用而更改。
事实之后是否可以更改DSN参数,还是需要创建全新的连接sql.DB
连接池?
您可能会问,为什么要检查时区是否已更改-它不是静态的吗?在负载平衡的数据库情况下应该做什么?理论上两个副本可以在不同的时区吗?
是否应该将所有带有时间戳记的列都用SQL UNIX_TIMESTAMP()
包装起来以规范化数据并避免这种麻烦?
我也可以涉猎时间,但我现在就停在这里。
答案 0 :(得分:0)
go
使用IANA的Time Zone Database和精确的区域名称。
试图逆向工程MySQL如何从(Linux)主机确定本地时区格式并在go
客户端中复制该逻辑(如@MattJohnson所指出的那样)被证明是不可靠的。
database/sql.DB
创建的 Open(drv, DSN)
–将对所有连接使用相同的DSN
。尽管sql.DB
只能创建一次并使用很多次-事后没有办法更改DSN
-因此在更改时,您需要创建一个全新的sql.DB
DSN
。
因此,更好的办法似乎是在传输给客户端之前,利用MySQL
将所有datetime
值从本地转换为UTC时区。这消除了在连接时通过DSN
设置数据库(可能未知)时区的麻烦。
一个有希望的选择是设置连接的会话时区:
SET @@session.time_zone = "+00:00";
go
客户端在任何给定时间都不知道他们可能正在使用哪个免费连接。因此,用如下转换函数包装所有datatime
列:
CONVERT_TZ(`STAMP_UPDATED`,@@session.time_zone,'+00:00')
确保时区计算在查询时完成,并且在连接重新连接等过程中不会丢失。
因此,DSN
现在不再需要指定loc
-因为UTC
是默认设置。实际上,DSN
仅需要后缀选项?parseTime=true
即可将datetime
转换为go
的本机time.Time
。
最后也是最重要的一点,这将适用于设置为任何时区的任何服务器。
对此answer的H / T。