再谈golang的sql链接dsn

  1. golang的time类型其中有一个field为loc *Location。这一点是golang和java不一样的地方

  2. 这是dsn的常见golang设置,这里说明下其中每个字段的含义

复制代码
root:root@tcp(127.0.0.1:3306)/user?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai&time_zone=%27%2B08%3A00%27
  1. parseTime 是否将date,datetime,timestamp 等时间类型直接转换成golang 的model中的time.Time类型

  2. time_zone,这个是设置当前session的时区。对timestamp类型的mysql数据,直接按照time_zone中设置的时区转换后给程序,这个转换是mysql做的,还不是驱动做的。其他类型的时间数据不会转换时区,返回的还是原来的字符串

  3. loc=Asia%2FShanghai。这个是和java不一样的地方,java没有这个field。这个loc就是对应golang的time类型其中有一个field为loc *Location这个字段的。就是为了程序员自己在代码中进行时区转换使用的。例如:

3.1 本来数据库字段是datetime类型。数据库是utc时区。插入datetime类型时候,选择的是now().因此数据库写入的就是utc的时区时间。此时parseTime=true&loc=Asia%2FShanghai的话,就会导致dao层的model的time.Time 类型的loc表示是+8时区的。也就是表示这个时间是+8区的时间。

此时程序员进行程序转换:

复制代码
var cstSh, _ = time.LoadLocation("Asia/Shanghai") // 上海
r := users[0].CreateTime.In(cstSh).Format("2006-01-02 15:04:05")

将不会有任何变化,数据库的时间在程序中还是会认为是+8时区的时间

3.2 如果loc不写,此时读取出来的time.Time的loc为utc时区。此时还是进行时区转换时:

var cstSh, _ = time.LoadLocation("Asia/Shanghai") // 上海

r := users[0].CreateTime.In(cstSh).Format("2006-01-02 15:04:05")

就会将utc时间转换为+8时区时间

3.3 也就是本身datetime类型的数据,读出来的time.Time一定是数据库的时间。这一点没有疑问。但是这个附带的loc的值,是由dsn的loc决定的。如果程序员不主动进行时区转换,那么这个时间一定是数据库存储的时间,如果代码中不主动进行时区转换,而是直接使用time.Time的话,这个loc完全没有使用场景。因为本身就不关注field为loc *Location这个内容。

  1. 矛盾和出路

4.1 now()的使用决定了数据库的datetime类型的字段值一定是mysql的时区一致

4.2 如果增加了dsn的timezone字段,仅能自动修改掉timestamp类型的时间。但是该时间的loc还是由dsn的链接决定的。同时存在datetime和timestamp将导致两难,举例如下:

  1. mysql是utc时间

  2. dsn= parseTime=true&loc=Asia%2FShanghai&time_zone=%27%2B08%3A00%27

  3. createtime = datetime。 modifytime = timestamp

  4. 读取的createtime对应的时间的loc=+8时区,但是值是utc时间的值。读取的modifytime的值是+8时区的值,但是loc=+8时区。也就是modifytime的时间是正确的了,但是createtime的时间和时区对不上

  5. 使用dsn= parseTime=true&loc=Asia%2FShanghai,不使用time_zone

  6. 这种情况下,读取的createtime对应的时间的loc=+8时区,但是值是utc时间的值。读取的modifytime的值是utc时间的值,对应的时间的loc=+8时区。依然是错误的

  7. 数据库now语句的使用,导致loc设置为和数据库的时区不一致的情况下,datetime类型值和时区一定存在矛盾。因为时区是loc决定的,值是数据库存储的值决定的。

8.因此loc的值必须和数据库的时区一致,而设置time_zone将没有什么意义,因为time_zone结合和时区不一样的loc的值,仅能将timestamp的值修改都正确。但是对使用now的其他字段的值,将无计可施。

相关推荐
F_D_Z8 小时前
【SQL】指定日期的产品价格
数据库·sql·mysql
程序员在线炒粉8元1份顺丰包邮送可乐9 小时前
Docker 部署生产环境可用的 MySQL 主从架构
mysql·docker·架构
刘媚-海外9 小时前
Go语言开发AI应用
开发语言·人工智能·golang·go
麦聪聊数据9 小时前
如何使用 QuickAPI 快速连接 MySQL 数据库并发布 RESTful API
数据库·sql·mysql·restful·数据服务
deepwater_zone9 小时前
Go语言核心技术
后端·golang
Run Freely93711 小时前
MySQL 数据库_01
数据库·mysql
小朋友,你是否有很多问号?11 小时前
mac本地安装mysql
数据库·mysql
斯普信专业组11 小时前
MySQL主从同步参数调优案例
mysql·主从
二哈不在线12 小时前
代码随想录二刷之“动态规划”~GO
算法·golang·动态规划