再谈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的其他字段的值,将无计可施。

相关推荐
奥尔特星云大使12 小时前
MySQL 慢查询日志slow query log
android·数据库·mysql·adb·慢日志·slow query log
来自宇宙的曹先生13 小时前
MySQL 存储引擎 API
数据库·mysql
老苏畅谈运维14 小时前
Oracle的connect by level在MySQL中的华丽变身
mysql·oracle
周杰伦的稻香17 小时前
MySQL5.7.44编译安装
数据库·mysql
叁沐19 小时前
MySQL 33 我查这么多数据,会不会把数据库内存打爆?
mysql
程序新视界1 天前
三种常见的MySQL数据库设计最佳实践
数据库·后端·mysql
没有bug.的程序员1 天前
MySQL 安全与权限管理:从基础到生产级安全实践
java·mysql·安全·adb·权限
数据与人1 天前
MySQL 8.0 InnoDB ReplicaSet 完整配置指南与切换
数据库·mysql·adb
合作小小程序员小小店1 天前
web网页开发,在线%推荐算法学院培养计划,图书推荐,基于Python,FlaskWeb,用户和物品推荐MySql
python·mysql·算法·flask·推荐算法
用手码出世界1 天前
MySQL存储过程
mysql