当前位置:网站首页>详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
2022-04-23 11:02:00 【liming89】
文章来源: 学习通http://www.bdgxy.com/
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坑内容请搜索菜鸟教程www.piaodoo.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持菜鸟教程www.piaodoo.com!
版权声明
本文为[liming89]所创,转载请带上原文链接,感谢
https://blog.csdn.net/liming89/article/details/124333871
边栏推荐
- Installing MySQL with CentOS / Linux
- Jupyter lab top ten high productivity plug-ins
- Visual common drawing (IV) histogram
- JVM - common parameters
- Learning note 5 - gradient explosion and gradient disappearance (k-fold cross verification)
- GO接口使用
- 关于JUC三大常用辅助类
- SWAT - Introduction to Samba web management tool
- 最强日期正则表达式
- Understand the key points of complement
猜你喜欢
【leetcode】199. Right view of binary tree
Introduction to neo4j authoritative guide, recommended by Qiu Bojun, Zhou Hongxiang, Hu Xiaofeng, Zhou Tao and other celebrities
Source insight 4.0 FAQs
How to quickly download vscode
SQL Server recursive query of superior and subordinate
语雀文档编辑器将开源:始于但不止于Markdown
Excel · VBA array bubble sorting function
解决方案架构师的小锦囊 - 架构图的 5 种类型
MIT:用无监督为世界上每个像素都打上标签!人类:再也不用为1小时视频花800个小时了
Jupyter lab top ten high productivity plug-ins
随机推荐
How to bind a process to a specified CPU
使用zerotier让异地设备组局域网
Use of SVN:
Solution architect's small bag - 5 types of architecture diagrams
Mba-day6 logic - hypothetical reasoning exercises
Mysql8. 0 installation guide
The songbird document editor will be open source: starting with but not limited to markdown
web三大组件(Servlet,Filter,Listener)
GO接口使用
MySQL common statements
MBA-day6 逻辑学-假言推理练习题
CUMCM 2021-b: preparation of C4 olefins by ethanol coupling (2)
Hikvision face to face summary
How to use JDBC callablestatement The wasnull () method is called to check whether the value of the last out parameter is SQL null
全栈交叉编译X86完成过程经验分享
Visual common drawing (I) stacking diagram
【leetcode】199. Right view of binary tree
Source insight 4.0 FAQs
闹钟场景识别
Visual common drawing (V) scatter diagram