详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑


Posted in MySQL onDecember 06, 2021

MySQL中如何表示当前时间?

其实,表达方式还是蛮多的,汇总如下:

 

Data Type “Zero” Value
DATE '0000-00-00'
TIME '00:00:00'
DATETIME '0000-00-00 00:00:00'
TIMESTAMP '0000-00-00 00:00:00'
YEAR 0000

datetime和timestamp这两种类型都是用于表示YYYY-MM-DD HH:MM:SS 这种年月日时分秒格式的数据,但两者还是有些许不同之处的。

结论

  • timestamp实际存储的是1970-01-01 00:00:00 UTC到目前的秒数占4字节(时间精度为毫秒和纳秒时会占用更多字节),故相当于是带时区的时间,通过设置会话的时区,会自动转换为设置的时区的时间
  • datetime存储的就是格式化后的字符串类似'2021-12-05 13:27:53.957033',不携带时区信息,在UTC和CST时区查询到的结果是一致的,例如在CST时区写入的'2021-12-05 13:27:53.957033',但是在UTC时区查询到的还是'2021-12-05 13:27:53.957033',如果没做时区转换,就相当于是直接将CST时间映射为UTC时间,但是实际上UTC时间比CST时间慢8个小时

验证

环境准备,简而言之就是存在一张表有timestamp字段和datetime字段,且当前服务端为CST时区

mysql> show create table test_time\G;
*************************** 1. row ***************************
Table: test_time
Create Table: CREATE TABLE `test_time` (
  `id` int NOT NULL AUTO_INCREMENT,
  `ts` timestamp(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  `dt` datetime(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.01 sec)

插入一条数据,当前CST时区下ts和dt结果相同

mysql> select * from test_time;
Empty set (0.00 sec)

mysql> insert into test_time() values();
Query OK, 1 row affected (0.00 sec)

mysql> select * from test_time;
+----+----------------------------+----------------------------+
| id | ts                         | dt                         |
+----+----------------------------+----------------------------+
|  3 | 2021-12-05 15:04:13.293949 | 2021-12-05 15:04:13.293949 |
+----+----------------------------+----------------------------+
1 row in set (0.00 sec)

将会话的时区设置为UTC时区再次查询,ts由于从CST时区变为UTC时区查询到的结果比之前慢8个小时,由于dt不带时区信息,结果不变

mysql> set time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_time;
+----+----------------------------+----------------------------+
| id | ts                         | dt                         |
+----+----------------------------+----------------------------+
|  3 | 2021-12-05 07:04:13.293949 | 2021-12-05 15:04:13.293949 |
+----+----------------------------+----------------------------+
1 row in set (0.01 sec)

从刚刚insert产生的binlog中也有体现,ts在binlog中存储为时间戳(从1970-01-01 00:00:00 UTC到目前的秒数)相当于带UTC时区信息,dt为不带时区信息,结果为格式化后的字符串2021-12-05 15:04:13.293949,主要关注倒数第4第5行,@2=1638687853.293949表示ts字段的值, @3='2021-12-05 15:04:13.293949'表示dt字段的值

[mysql %] mysqlbinlog -v --base64-output=decode-rows ./mysqlbin.000012
... ...
SET @@SESSION.GTID_NEXT= '1cf4493a-dafd-11eb-944c-4016af29c14c:1416767'/*!*/;
# at 14220
#211205 15:04:13 server id 1  end_log_pos 14308 CRC32 0x1fd913a3 Query thread_id=137 exec_time=0 error_code=0
SET TIMESTAMP=1638687853.293949/*!*/;
BEGIN
/*!*/;
# at 14308
#211205 15:04:13 server id 1  end_log_pos 14368 CRC32 0xbb8937fb Table_map: `testa`.`test_time` mapped to number 121
# at 14368
#211205 15:04:13 server id 1  end_log_pos 14423 CRC32 0x2e0a3baa Write_rows: table id 121 flags: STMT_END_F
### INSERT INTO `testa`.`test_time`
### SET
###   @1=3
###   @2=1638687853.293949
###   @3='2021-12-05 15:04:13.293949'
# at 14423
#211205 15:04:13 server id 1  end_log_pos 14454 CRC32 0x68cee280 Xid = 1416
COMMIT/*!*/;

  • 如果在做DTS相关项目时,使用解析MySQL binlog的开源工具,例如github.com/go-mysql-org/go-mysql,如果配置了parseTime=true会将timestamp类型字段解析为Local时间,将datetime类型解析为UTC时间,也可配置为false获取到的就是字符串(timestamp已转换为会话时区的时间,datetime就是binlog中原生的字符串)自己解析,如果parseTime=true且不是使用的UTC时间插入的datetime字段,理论上拿到的时间已经不正确了,相当于直接将CST的2021-12-05 15:04:13.293949转换为了UTC的2021-12-05 15:04:13.293949,实际上应该转换为UTC的2021-12-05 07:04:13.293949才正确
  • 如果刚好业务需求中有time.Now()获取的Local时间和datetime类型字段比较的场景,需要注意时区问题,或者将时间都去掉时区,转换为格式化后的字符串相比较
  • 由于datetime本身就不带时区信息,除了转换UTC时间,也没有更好的选择,所以很坑!

到此这篇关于详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑的文章就介绍到这了,更多相关MySQL timestamp和datetime坑内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
Mysql服务添加 iptables防火墙策略的方案
Apr 29 MySQL
MySQL Threads_running飙升与慢查询的相关问题解决
May 08 MySQL
MySQL数据库压缩版本安装与配置详细教程
May 21 MySQL
一看就懂的MySQL的聚簇索引及聚簇索引是如何长高的
May 25 MySQL
MySQL中distinct与group by之间的性能进行比较
May 26 MySQL
MYSQL(电话号码,身份证)数据脱敏的实现
May 28 MySQL
浅谈MySQL next-key lock 加锁范围
Jun 07 MySQL
Mysql数据库按时间点恢复实战记录
Jun 30 MySQL
MySQL命令无法输入中文问题的解决方式
Aug 30 MySQL
MySQL中varchar和char类型的区别
Nov 17 MySQL
彻底解决MySQL使用中文乱码的方法
Jan 22 MySQL
MySQL数据库实验实现简单数据库应用系统设计
Jun 21 MySQL
mysql中整数数据类型tinyint详解
Dec 06 #MySQL
SQL注入详解及防范方法
Dec 06 #MySQL
防止web项目中的SQL注入
Dec 06 #MySQL
mysql创建存储过程及函数详解
Dec 04 #MySQL
mysql5.6主从搭建以及不同步问题详解
MySQL图形化管理工具Navicat安装步骤
全面盘点MySQL中的那些重要日志文件
You might like
PHP4 与 MySQL 数据库操作函数详解
2006/12/06 PHP
PHP技术开发技巧分享
2010/03/23 PHP
PHP中的一些常用函数收集
2015/05/26 PHP
解决更换PHP5.4以上版本后Dedecms后台登录空白问题的方法
2015/10/23 PHP
javascript下查找父节点的简单方法
2007/08/13 Javascript
jquery 插件学习(六)
2012/08/06 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
JS动态修改表格cellPadding和cellSpacing的方法
2015/03/31 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
Sort()函数的多种用法
2016/03/20 Javascript
JQuery PHP图片在线裁剪实例
2020/07/27 Javascript
AngularJS实践之使用NgModelController进行数据绑定
2016/10/08 Javascript
layui分页效果实现代码
2017/05/19 Javascript
Angular.js自动化测试之protractor详解
2017/07/07 Javascript
layui前端框架之table表数据的刷新方法
2018/08/17 Javascript
简单了解微信小程序的目录结构
2019/07/01 Javascript
基于JS实现数字动态变化显示效果附源码
2019/07/18 Javascript
解决Vue中使用keepAlive不缓存问题
2020/08/04 Javascript
Python简明入门教程
2015/08/04 Python
深入讲解Java编程中类的生命周期
2016/02/05 Python
网红编程语言Python将纳入高考你怎么看?
2018/06/07 Python
ubuntu 16.04下python版本切换的方法
2019/06/14 Python
Python连接字符串过程详解
2020/01/06 Python
python实现在线翻译功能
2020/03/03 Python
pycharm解决关闭flask后依旧可以访问服务的问题
2020/04/03 Python
Selenium自动化测试工具使用方法汇总
2020/06/12 Python
css3 实现圆形旋转倒计时
2018/02/24 HTML / CSS
Superdry极度乾燥官网:日本街头风格,纯英国制造品牌
2016/10/31 全球购物
精美的手工家居和生活用品:Nkuku
2019/11/01 全球购物
AJax面试题
2014/11/25 面试题
材料加工硕士生求职信
2013/10/10 职场文书
2014年社区学雷锋活动总结
2014/03/09 职场文书
工程承包协议书范本
2014/09/29 职场文书
优秀教师个人总结
2015/02/11 职场文书
大学学生会主席竞选稿
2015/11/19 职场文书
2016廉洁教育心得体会
2016/01/20 职场文书