Mysql中DATE,DATETIME,和TIMESTAMP 的区别

1. DATE

  • 用途:只存储日期(年、月、日),不包含时间部分。
  • 格式YYYY-MM-DD
  • 范围:从 1000-01-019999-12-31
  • 存储:不存储时区信息,存储的值与时区无关。
  • 占用字节:3 字节
  • 应用场景:适合只需要存储日期的场景,如出生日期、节假日、预约日期等。

示例:

1
2
3
sql
SELECT DATE('2024-09-12');
-- 返回: 2024-09-12

2. DATETIME

  • 用途:存储日期和时间(年、月、日、时、分、秒),不包含时区。
  • 格式YYYY-MM-DD HH:MM:SS
  • 范围:从 1000-01-01 00:00:009999-12-31 23:59:59
  • 存储:不考虑时区,也不会自动进行时区转换。
  • 占用字节:8 字节
  • 应用场景:适合需要精确记录某个时刻的场景,但无需考虑时区影响,如事件时间戳、日志记录等。

示例:

1
2
3
sql
SELECT DATETIME('2024-09-12 14:30:00');
-- 返回: 2024-09-12 14:30:00

3. TIMESTAMP

  • 用途:存储日期和时间(年、月、日、时、分、秒),包含时区信息。
  • 格式YYYY-MM-DD HH:MM:SS
  • 范围:从 1970-01-01 00:00:01 UTC 到 2038-01-19 03:14:07 UTC(32 位整数的范围)。
  • 存储:存储的是 UTC 时间,根据连接的时区设置,在存储和检索时会自动转换时区。
  • 占用字节:4 字节
  • 自动更新:可以使用 CURRENT_TIMESTAMP 来自动存储插入或更新的当前时间。
  • 应用场景:适合需要记录具体事件发生的精确时间且需要处理跨时区的场景,比如日志、创建时间和更新时间字段。

示例:

1
2
3
sql
SELECT TIMESTAMP('2024-09-12 14:30:00');
-- 根据服务器时区和客户端时区返回值不同

主要区别总结:

特性 DATE DATETIME TIMESTAMP
存储内容 仅日期 日期 + 时间 日期 + 时间(含时区转换)
时区相关
范围 1000-01-019999-12-31 1000-01-01 00:00:009999-12-31 23:59:59 1970-01-012038-01-19
占用空间 3 字节 8 字节 4 字节
适用场景 只需日期 日期和时间,无需时区转换 日期和时间,跨时区场景

选择合适的类型取决于你是否需要时区支持以及存储的日期和时间精度。


思考:

2038年到来时,使用 TIMESTAMP 类型的 MySQL 数据库可能会面临一个问题,这个问题称为2038年问题,或者Unix时间戳溢出问题。这个问题主要影响以32位有符号整数存储的时间数据。

为什么会出现2038年问题?
  • TIMESTAMP类型的存储TIMESTAMP 在 MySQL 中基于 Unix 时间戳存储,该时间戳记录自 1970 年 1 月 1 日 UTC 时间的秒数。
  • 32位有符号整数:MySQL 的 TIMESTAMP 数据类型传统上使用 32 位有符号整数来存储秒数。32 位有符号整数的最大值为 2147483647,对应的日期时间为 2038年1月19日 03:14:07 UTC
  • 溢出问题:当这个时间戳超过 2147483647 时,整数会溢出,无法再表示有效的时间,这将导致日期和时间出现错误,可能回到1970年(或者表现为负数时间)。
到了2038年会发生什么?
  1. 时间溢出:到达 2038年1月19日 03:14:07 UTC 后,如果 MySQL 依旧使用 32 位 TIMESTAMP 存储,新的 TIMESTAMP 值将无法表示超过这个时间的日期,系统可能会返回错误时间(通常是负数,或回到1970年1月1日)。
  2. 应用和数据崩溃风险:如果应用程序或数据库依赖这些时间戳,那么在处理超过2038年的时间数据时,可能会发生异常行为、崩溃或者数据丢失。
解决方案
  1. 升级到64位系统:64位系统可以扩展时间戳的范围。现代 MySQL 版本在支持 64 位系统上扩展了 TIMESTAMP,这允许存储和处理超出 2038 年的日期。
    • 64位整数 可以表示更长的时间范围,大约是从公元前29万年到公元29万年之间,所以2038年问题在这种情况下不会再发生。
  2. 使用 DATETIME 类型:如果不需要时区转换,也可以将字段类型从 TIMESTAMP 改为 DATETIMEDATETIME 直接存储日期和时间,不依赖 Unix 时间戳,不会遇到2038年问题。
    • 注意DATETIME 不会在存储或检索时自动转换时区。
  3. 及时更新数据库版本:最新版本的 MySQL 和其他数据库通常已经解决了这个问题,通过使用 64 位时间戳,确保支持超出2038年的时间。