桓楠百科网

编程知识、经典语录与百科知识分享平台

MySQL彻底解决2038年问题(mysql2054)

部分使用MySQL的数据库维护人员或者软件开发人员可能已经知道MySQL存在2038年问题,网络上有很多解决思路,但是很大一部分都是错误的,实际解决不了问题。针对于此,个人基于实际模拟的2038年MySQL问题,以及针对性解决后的测试验证,真实还原MySQL的2038年问题解决过程。

一、背景

MySQL的2038年问题源于其早期版本中TIMESTAMP类型的时间存储机制。该类型使用32位有符号整数表示自1970年1月1日(UTC)以来的秒数,最大值限制为2^31-1(即2038年1月19日03:14:07,对应北京时间是2038年1月19日11:14:07)。超过此时间后,时间戳将回滚至1970年1月1日,导致数据库时间计算错误。这一问题最直观的影响是MySQL服务会自动停止运行,对所有依赖MySQL数据库的系统影响深远。最简单的验证方法是在运行MySQL服务的环境中,手动更改系统时间超过2038年1月19日,会发现MySQL服务瞬时停止。

二、解决思路

解决MySQL 2038年问题的办法只有一个,那就是升级MySQL版本

MySQL在8.0.28版本解决了2038年问题,其官方在该版本的改动说明中进行了描述:

The functions FROM_UNIXTIME(), UNIX_TIMESTAMP(), and CONVERT_TZ() now handle 64-bit values on platforms that support them, including 64-bit versions of Linux, MacOS, and Windows.

On compatible platforms, FROM_UNIXTIME() now accepts a maximum argument of 32536771199.999999 seconds, corresponding to '3001-01-18 23:59:59.999999' UTC (including the optional fraction of up to 6 digits). If the argument is larger than this, the function returns NULL.

On compatible platforms, UNIX_TIMESTAMP() now accepts a maximum value of '3001-01-18 23:59:59.999999' UTC, corresponding to 32536771199.999999 seconds since the Unix Epoch. If the argument is larger than this, the function returns 0.

In addition, on compatible platforms, CONVERT_TZ() now performs time zone conversion beyond 2038, up to '3001-01-18 23:59:59.999999' UTC. If the datetime argument exceeds this value, the argument is returned unchanged. This “no-op” behavior is the same as previously with values beyond '2038-01-19 03:14:07.999999' UTC.

The behavior of these 3 functions on 32-bit platforms is unchanged.

The behavior of the TIMESTAMP type is also unaffected by this change; its maximum allowed value remains '2038-01-19 03:14:07.999999' UTC, regardless of platform. For dates futureward of this, use the MySQL DATETIME type instead. (WL #14630)

三、具体操作

截止今天,MySQL官网可以下载的稳定高版本有8.0.42和8.4.5两个版本。其中,8.4.5是LTS版本(Long Term Support,长期支持),相对技术支持有保障一些。

大家可以根据需要下载配套平台的安装包进行安装更新,也可以下载源码包进行自定义编译安装。在基于源码包进行编译时,需要考虑平台的GCC版本是否满足需求,特别是一些嵌入式平台,实际平台环境可能是较久时间之前打造的,对应的GCC版本相对较老,可能没有新版本GCC。

通过查看MySQL源码包中的“cmake/os/Linux.cmake”文件,可以知道该版本MySQL源码编译所需的GCC版本号。具体可以打开该文件并搜索“GCC”字样,可以看到类似信息:

# We require at least GCC 7.1 Clang 5

IF(NOT FORCE_UNSUPPORTED_COMPILER)

IF(MY_COMPILER_IS_GNU)

IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1)

MESSAGE(FATAL_ERROR "GCC 7.1 or newer is required")

ENDIF()

ELSEIF(MY_COMPILER_IS_CLANG)

IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)

MESSAGE(FATAL_ERROR "Clang 5 or newer is required!")

ENDIF()

ELSE()

MESSAGE(FATAL_ERROR "Unsupported compiler!")

ENDIF()

ENDIF()

通过该方法,我们知道编译8.0.42版本MySQL所需的GCC最低版本为7.1,而编译8.4.5版本MySQL所需的GCC最低版本为10

四、总结

通过升级MySQL到当前最新版本(实际不一定需要最新版本,但是确保不低于8.0.28版本),然后再调整系统时间超过2038年1月19日,会发现MySQL服务依然正常运行,对应信息系统也是正常运行,可确认MySQL的2038年问题已彻底解决。对于需要长期稳定运行和维护的系统,建议提前考虑对应的问题解决,避免到点前再处理而导致措手不及。

五、联系

如果您在操作中遇到疑问或有其他想法,欢迎联系我,我会尽快回复并提供帮助!

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言