当前位置: 首页 > news >正文

MySQL时间类型

1. 为什么会有这么多时间类型

早期 MySQL 只有 DATE、TIME、YEAR,随着互联网业务对毫秒级、全球多活、历史数据的需求,逐渐扩展到 DATETIME(fsp)、TIMESTAMP(fsp)。每种类型在存储空间、时区处理、范围、性能上各有取舍,选错类型往往导致“线上时区惨案”或“索引失效”。

2. 五大原生类型

类型格式示例范围存储(字节)时区感知备注
DATE2025-08-091000-01-01 ~ 9999-12-313只存日期
TIME[(fsp)]14:35:07.123-838:59:59.000000 ~ 838:59:59.0000003 + fsp/2可存时长
DATETIME[(fsp)]2025-08-09 14:35:07.1231000-01-01 00:00:00.000000 ~ 9999-12-31 23:59:59.9999995 + fsp/2推荐存“绝对时间”
TIMESTAMP[(fsp)]2025-08-09 14:35:07.1231970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC4 + fsp/2存 epoch 秒
YEAR20251901 ~ 21551节省空间

fsp:fractional seconds precision(0-6),MySQL 8.0 默认 0。

3. 内部存储格式

• DATE:3 byte,小端序,第 1 字节存 (year-1000)*16+month,后两字节存 day。
• DATETIME(0):5 byte,年月日时分秒各压缩成 bit。
• TIMESTAMP:4 byte 有符号 int,存 epoch 秒,fsp 额外占 1-3 byte。
• 存储层完全透明,无需关心,但理解后更容易解释“为什么 DATETIME 范围更大”。

4. 时区、夏令时与 2038 问题

TIMESTAMP 在写入/读取时,通过系统变量 time_zone 自动 UTC↔会话时区转换,因此同一行数据在不同客户端可能显示不同字符串。
DST(夏令时)切换当天可能出现“重复 02:00”或“跳过 02:00”,MySQL 以 UTC epoch 秒存储,可规避该问题。
2038 问题:有符号 32 位 epoch 秒上限 2038-01-19;8.0 已支持 64 位,且官方建议迁移到 DATETIME(6) 或 BIGINT 保存微秒 epoch。

5. 性能与索引:DATETIME vs TIMESTAMP

• 存储空间:TIMESTAMP(0) 4B < DATETIME(0) 5B;带 fsp 后差距缩小。
• 索引:二者在 BTREE 里都是按字节排序,性能无差异;但 TIMESTAMP 范围小,回表过滤更快。
• 分区表:TIMESTAMP 无法直接做 RANGE COLUMNS 分区(因为内部是 INT);DATETIME 可直接按天分区。

6. 8.0 新特性

a) fsp 最大 6 位,默认 0;
b) information_schema.time_zone* 表支持夏令时历史更完整;
c) NOW() 结果在 binlog/复制中持久化,保证主从时间一致;
d) cast('2025-08-09 14:35:07.123456' as datetime(6)) 不再四舍五入;
e) ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE 支持在线扩大 fsp。

7. 实战场景 & 代码片段

场景 1:订单创建时间(全球用户)

CREATE TABLE orders (id BIGINT PRIMARY KEY,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)
) ENGINE=InnoDB;

理由:不涉及时区转换,可读性强,范围足够。

场景 2:用户最后登录时间(需要自动转换时区)

CREATE TABLE user_login (user_id BIGINT PRIMARY KEY,last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

客户端会话各自设置 SET time_zone = '+08:00',即可自动显示本地时间。

场景 3:事件时长统计

SELECT TIMESTAMPDIFF(MICROSECOND, start_time, end_time) AS duration_us
FROM events;

8. 常见误区与避坑清单

  1. 把生日存成 TIMESTAMP → 范围不够,1970 以前会报错。
  2. SELECT * FROM t WHERE DATE(create_time) = '2025-08-09' → 无法使用索引;改成 BETWEEN '2025-08-09 00:00:00' AND '2025-08-09 23:59:59'
  3. 以为 DATETIME(0) 和 DATETIME(3) 空间一样 → 实际 5 vs 6 byte,大量行会浪费存储。
  4. 用 VARCHAR(19) 存时间 → 排序/比较需要 CAST,性能差且易出格式错误。
  5. 8.0 之前把 TIMESTAMP 默认值设为 ‘0000-00-00 00:00:00’ → 会报 “Invalid default value”。

9. 小结


• 日期类 → DATE
• 绝对时间 → DATETIME(fsp)
• 时区感知 → TIMESTAMP(fsp)
• 只存年份 → YEAR
• 存时长 → TIME(fsp)

MySQL 8.0 之后,64 位 TIMESTAMP 已在实验室分支测试,未来有望彻底解决 2038 问题;官方也在考虑原生支持 TIMESTAMP WITH TIME ZONE(类似 PostgreSQL),让我们拭目以待。

http://www.dtcms.com/a/323629.html

相关文章:

  • windows上LM-Studio下载安装教程
  • 谷歌搜索 sg_ss 逆向分析
  • 自闭和标签形式(self-closing tags)和标准标签形式
  • [概率 DP]808. 分汤
  • C++入门学习3
  • 开漏和推挽模式的区别
  • QT第一讲- Qt初探
  • XSS攻击演示
  • 常用信号深度解析(SIGINT、SIGPIPE、SIGALRM、SIGTERM等)
  • 101-基于Python的个性化音乐推荐系统
  • 码上爬第三题【协程+浏览器调试检测】
  • 本文章分享一个本地录音和实时传输录音给app的功能(杰理)
  • [GPU]什么是“硬件TL”在UnityURP中的体现
  • 疏老师-python训练营-Day40训练和测试的规范写法
  • 并发编程基础:继承Thread vs 实现Runnable - 深入解析与最佳实践
  • Tob大客户销售面试经验
  • 华为交换机进阶功能和场景化配置
  • 最长回文子串(马拉车/Manacher‘s )算法
  • P1053 [NOIP 2005 提高组] 篝火晚会
  • 【C/C++】详解内存对齐问题,C语言内存对齐整理
  • vulhub-Beelzebub靶机
  • 计算网络相关知识
  • 第15届蓝桥杯Scratch图形化省赛初级组2024年8月24日真题
  • 模型微调与RAG在问答系统中的对比分析
  • [激光原理与应用-205]:光学器件 - LD与DFB的比较
  • leetcode 11. 盛最多水的容器 -java
  • Kubernetes CronJob bug解决
  • B站小波变换视频笔记
  • 原创邮件合并Python工具使用说明(附源码)
  • python---变量作用域