MySQL中,日期、时间与时间戳三种数据类型的区别

在 MySQL 中存储日期和时间有几种不同的方法,想要选择正确的方式就需要大家理解要存储的数据类型以及 MySQL 如何处理这些数据类型。

这篇文章就带大家梳理一下MySQL的这些日期与时间的类型。

MySQL的五种时间数据类型

在MySQL中,提供了五种可以存储时间数据的列类型:

  • DATE
  • DATETIME
  • TIMESTAMP
  • YEAR
  • TIME

每种列类型存储的数据略有不同,具有不同的最小值和最大值,并且需要不同的存储空间大小。

下表显示了每种列类型及其相关属性:

列类型 数据类型 字节 最小值 最大值
DATE 仅日期 3 1000-01-01 9999-12-31
DATETIME 日期 + 时间 8 1000-01-01 00:00:00 9999-12-31 23:59:59
TIMESTAMP 日期 + 时间 4 1970-01-01 00:00:00 2038-01-19 03:14:17
YEAR 仅年份 1 1901 2155
TIME 仅时间 3 -838:59:59 838:59:59

下面,我们针对上述的数据类型,来进行相应的分析和讲解。

日期、年份和时间

上面的表中展示了五种类型,在实践的过程中,我们首先需要思考的一个问题就是:在此场景下,我需要存储什么样的数据?

DATE类型

如果只需要存储日期而无需时间信息,那么选择非常简单------使用 DATE 类型。例如,它适合存储生日、纪念日、员工入职日期等日期相关信息。

DATE 类型非常简洁,仅需要 3 字节即可存储从公元 1000 年到 9999 年范围内的大量日期。

YEAR类型

类似地,如果只需要存储年份而无需日期信息,可以使用 YEAR 类型。虽然这种列类型不常见,但当你确实需要它时,它也能有效地达成目标。

YEAR 类型非常紧凑,仅占用 1 字节。不过其范围较小,仅覆盖从 1901 年到 2155 年。如果你需要更大的范围,可以考虑使用带符号或无符号的小整数(SMALLINT)。

TIME类型

最后是 TIME 类型,用于存储时间(hh:mm:ss 格式)。它的有效范围比常规时间(00:00:0023:59:59)更广,因为它可以存储时间间隔和墙上时钟时间。其范围为 -838:59:59838:59:59,大约覆盖正负 35 天。

如果你只需要存储时间或持续时长而无需日期,TIME 类型非常适合。如果需要一起存储日期和时间,最好使用 DATETIMETIMESTAMP ,以一种逻辑单元存储它们,而不要分成两列。

TIMESTAMP 与 DATETIME 的合法范围

在MySQL中,DATETIMETIMESTAMP 类型都适合存储特定时间的引用。例如,如果需要存储 2029 年 2 月 14 日上午 8:47,可以使用任意一种列类型。

选择 DATETIME 或 TIMESTAMP 的依据就是具体的业务场景所需,两者本身没有优劣之分。

存储大小

TIMESTAMP 类型的存储大小为 4 字节 ,而 DATETIME 列类型为 8 字节。虽然存储空间并不昂贵,但设计表结构时,我们通常希望选择能够容纳所有数据范围的最小列类型。设计时无需"过度慷慨"。

由于 TIMESTAMP 的存储大小较小,其合法范围也相应较窄。

MySQL 中的 2038 问题

TIMESTAMP 的时间范围从 1970-01-01 00:00:002038-01-19 03:14:17。但在使用TIMESTAMP时,不可避免的会让我们想起著名的"2038 年问题",它也被标记为Y2038、Y2K38 或"Epochalypse"(时间纪元末日)。

2038 年问题源于计算 Unix 时间的系统。Unix 时间是从 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元)开始的经过的秒数,这些系统使用带符号的 32 位整数来存储时间。

带符号的 32 位整数只能存储范围为 -2^312^31 - 1 的值。能够准确表示的最大时间戳对应于 Unix 纪元后 2^31 - 1 秒,即 2038 年 1 月 19 日 03:14:07 UTC。

因此,如果需要存储 2038 年以后的日期,那就应当避免使用 TIMESTAMP,而应该选择 DATETIME。

对于当前应用,仍有许多场景可以使用 TIMESTAMP。例如,当记录动作发生的时间时,例如以下列:

  • updated_at
  • created_at
  • deleted_at
  • archived_at
  • posted_at

这些列通常由应用程序填充,只需记录事件发生的当前时间。在未来十多年内,TIMESTAMP 完全能够满足此类需求。即便到了 2038 年,相信也会有解决方案的。

何时使用 DATETIME

鉴于 TIMESTAMP 的合法值范围较窄,当需要存储 1970 至 2038 年范围之外的日期时间时,通常使用 DATETIME。

如果该字段是用户输入内容,可能需要选择 DATETIME 或验证输入内容是否在 TIMESTAMP 的范围内。

DATETIME 与 TIMESTAMP 的时区处理

除了存储大小和合法范围不同之外,DATETIME 与 TIMESTAMP 的另一个区别在于它们对时区的处理方式。时区对几乎所有开发者来说都是难题,而在 MySQL 中也不例外。

DATETIME 的时区处理

DATETIME 不会对时区进行任何处理。如果你向数据库写入一个值 2029-02-14 08:47,那么无论服务器或连接的时区如何设置,你始终会得到 2029-02-14 08:47

TIMESTAMP 的时区处理

TIMESTAMP 则会尝试"帮助你"处理时区。根据 MySQL 文档:

MySQL 会将 TIMESTAMP 类型的数据从当前时区转换为 UTC 存储,并在查询时从 UTC 转为当前时区。(这不会发生在其他类型,例如 DATETIME。)默认情况下,每个连接的当前时区是服务器的时区。

我们通过小示例验证这一点。首先创建包含 DATETIME 和 TIMESTAMP 列的表:

sql 复制代码
CREATE TABLE timezone_test (
    `timestamp` TIMESTAMP,
    `datetime` DATETIME
);

然后将连接时区设置为 UTC 并插入数据:

sql 复制代码
SET SESSION time_zone = '+00:00';
​
INSERT INTO timezone_test VALUES ('2029-02-14 08:47', '2029-02-14 08:47');
​
SELECT * FROM timezone_test;
​
-- | timestamp           | datetime            |
-- |---------------------|---------------------|
-- | 2029-02-14 08:47:00 | 2029-02-14 08:47:00 |

目前看起来不错,插入和读取的值完全一致。接下来我们将时区改为 -05:00 并再次查询表:

sql 复制代码
SET SESSION time_zone = '-05:00';
SELECT * FROM timezone_test;
​
-- | timestamp           | datetime            |
-- |---------------------|---------------------|
-- | 2029-02-14 03:47:00 | 2029-02-14 08:47:00 |

你会发现 TIMESTAMP 列被调整了 5 小时,而 DATETIME 列保持不变。

在实践中,如果服务器和连接时区总是设置为 UTC,这通常不会有问题。但如果不是这样,你可能会惊讶地发现存入数据库的值与取出的值不完全相同。

小结

本篇文章多个维度的对比,科普了一下MySQL中日期、时间和时间戳等数据类型在具体使用时的区别,在每个类型的具体实践中,还有许多最佳实践,在使用时可以尝试更进一步深入的了解。

相关推荐
Pa2sw0rd丶6 小时前
Fastjson 反序列化漏洞深度解析:从原理到实战防护
java·后端·安全
q***64976 小时前
SpringSecurity踢出指定用户
android·前端·后端
Coding_Doggy6 小时前
链盾shieldchiain | 团队功能、邀请成员、权限修改、移除成员、SpringSecurity、RBAC权限控制
java·开发语言·数据库
q***76666 小时前
SpringSecurity 实现token 认证
android·前端·后端
凯子坚持 c6 小时前
不用复杂配置!本地 Chat2DB 秒变远程可用,跨网操作数据库就这么简单
数据库
q***65696 小时前
Windows环境下安装Redis并设置Redis开机自启
数据库·windows·redis
川白6 小时前
为防在家摸鱼,用计网知识实践屏蔽B站!
后端
q***96587 小时前
Windows版Redis本地后台启动
数据库·windows·redis
吃果冻不吐果冻皮7 小时前
DeepSeek 视觉语言大模型技术演进(从DeepSeek VL/VL2到DeepSeek OCR)
后端
申阳7 小时前
Day 15:01. 基于 Tauri 2.0 开发后台管理系统-Tauri 2.0 初探
前端·后端·程序员