MySQL timestamp 2038 年限制解决方案?

MySQL timestamp 到2038如何解决

目前MySQL版本8.0.29,尝试了改sql_mode但是没有效果,只能把字段改为datetime吗
image.png

MySQL升级到了8.0.36,设置了sql_mode,新建了一张表设置日期超过2038还是不行
image.png
image.png

阅读 2.4k
avatarAI BotBETA

MySQL 的 TIMESTAMP 数据类型在存储时间戳时有一个已知的限制,这是由于其底层表示是基于 Unix 时间戳的 32 位整数。Unix 时间戳从 1970 年 1 月 1 日开始计算,以秒为单位,由于它是 32 位的,因此它只能表示到 2038 年 1 月 19 日 03:14:07 UTC 的时间范围。一旦超过这个时间点,TIMESTAMP 数据类型可能会遇到溢出问题。

对于 MySQL 8.0.29 版本,解决这个限制的方法有几种:

  1. 使用 DATETIME 数据类型
    如果你不需要考虑时区变化,或者你的应用程序可以处理时区转换,那么将字段类型从 TIMESTAMP 改为 DATETIME 是一个简单直接的解决方案。DATETIME 类型可以表示从 1000-01-01 00:00:00 到 9999-12-31 23:59:59 的日期和时间范围。

    示例:

    ALTER TABLE your_table_name MODIFY your_timestamp_column_name DATETIME;
  2. 使用 BIGINT 和 UNIX 时间戳
    如果你需要更高的时间精度或超过 DATETIME 范围的时间戳,你可以使用 BIGINT 数据类型来存储 Unix 时间戳(以毫秒或微秒为单位)。这样,你可以存储从 1970 年 1 月 1 日至今的任意时间,并且能够扩展到未来很长的时间。

    示例:

    ALTER TABLE your_table_name MODIFY your_timestamp_column_name BIGINT UNSIGNED;

    在应用程序中,你可以使用相应的函数来将 BIGINT 类型的 Unix 时间戳转换为人类可读的日期和时间格式。

  3. 升级 MySQL 版本
    虽然 MySQL 8.0.29 版本仍然受到这个限制,但未来的 MySQL 版本可能会提供对 TIMESTAMP 数据类型的改进或新的数据类型来支持更广泛的日期范围。检查 MySQL 的官方文档和更新日志,以了解是否有关于此问题的最新进展。
  4. 避免使用 TIMESTAMP
    如果你不需要 MySQL 自动更新 TIMESTAMP 字段的功能(例如,在每次行更新时自动更新最后一个修改时间),则可以避免使用 TIMESTAMP 数据类型,并使用上述提到的 DATETIME 或 BIGINT 类型来替代。

请注意,更改列的数据类型可能会影响现有的应用程序代码和查询,因此在进行更改之前,请确保你了解这些更改的影响,并在生产环境中进行充分的测试。

2 个回答

升级后配置也不行,最后还是改表了,这里补充一个批量改表方式,执行下面查询sql,得到的sql语句复制出来然后执行就行了。

改表需谨慎,请在测试数据库测试没问题再操作!改表需谨慎,请在测试数据库测试没问题再操作!改表需谨慎,请在测试数据库测试没问题再操作!

SELECT CONCAT(
    'ALTER TABLE `', t.TABLE_NAME, '` MODIFY `',t. COLUMN_NAME, '` DATETIME COMMENT ''',
    IFNULL(t.column_comment, ''),
    ''';'
) AS alter_statement
FROM (
    SELECT TABLE_NAME, COLUMN_NAME
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = 'your_table'
    AND COLUMN_TYPE LIKE '%timestamp%'
) AS cols
LEFT JOIN (
    SELECT TABLE_NAME, COLUMN_NAME, COLUMN_COMMENT
    FROM information_schema.COLUMNS
    WHERE TABLE_SCHEMA = 'your_table'
    AND COLUMN_COMMENT IS NOT NULL
) AS t
ON cols.TABLE_NAME = t.TABLE_NAME AND cols.COLUMN_NAME = t.COLUMN_NAME
WHERE t.TABLE_NAME IS NOT NULL;
新手上路,请多包涵

数据库字段使用 BIGINT 类型,程序中使用 UNIX 时间戳(比如:1714358781)。前端js格式化时*1000,就完美解决。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题