1. 问题描述
如果时间来到了 2038 年,或者手动将操作系统的本地时间调整为 2038 年,比如 2038-12-12,你会发现正在运行的 MySQL 会自动关闭,重启后同样会自动关闭,无法使用,查看错误日志,会有下面的一段错误信息,MySQL 不支持 2038 年之后的日期。
This MySQL server doesn't support dates later then 2038
2038-12-12T12:12:15.989231+08:00 7 [Warning] Current time has got past year 2038. Validating current time with 5 iterations before initiating the normal server shutdown process.
2038-12-12T12:12:15.989298+08:00 7 [Warning] Iteration 1: Current time obtained from system is greater than 2038
2038-12-12T12:12:15.989313+08:00 7 [Warning] Iteration 2: Current time obtained from system is greater than 2038
2038-12-12T12:12:15.989320+08:00 7 [Warning] Iteration 3: Current time obtained from system is greater than 2038
2038-12-12T12:12:15.989326+08:00 7 [Warning] Iteration 4: Current time obtained from system is greater than 2038
2038-12-12T12:12:15.989332+08:00 7 [Warning] Iteration 5: Current time obtained from system is greater than 2038
2038-12-12T12:12:15.989338+08:00 7 [ERROR] This MySQL server doesn't support dates later then 2038
2. 原因分析
MySQL timestamp 支持的最大时间范围是 '1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999',在源码 sql/sql_parse.cc 的 dispatch_command() 函数里,有一段代码,检测当前时间是否超过 2038 年,如果超过,则会立即停止 MySQL。
来看一下源码里(5.7.19源码),这段代码的注释:
/*
If the time has gone past 2038 we need to shutdown the server. But
there is possibility of getting invalid time value on some platforms.
For example, gettimeofday() might return incorrect value on solaris
platform. Hence validating the current time with 5 iterations before
initiating the normal server shutdown process because of time getting
past 2038.
*/
/*
If the time has got past 2038 we need to shut this server down.
We do this by making sure every command is a shutdown and we
have enough privileges to shut the server down
TODO: remove this when we have full 64 bit my_time_t support
*/
从以上这两段注释来看,应该是 MySQL 内部变量 my_time_t 不支持 64 位,在到达 2038 年之后,MySQL 无法执行任何命令,直接关闭。
3. 影响范围
目前 5.7 以及 8.0 的最新版本,都包含这一段代码逻辑,也就是现有的版本都会受到影响,在 2038 年都会自动停止。
- 5.7.32(当前 5.7 的最新版本)
- 8.0.22(当前 8.0 的最新版本)
本文测试版本为 5.7.19
4. 解决方案
期待 MySQL 官方后续尽快开发完全支持 my_time_t 64位的版本,在 2038 年之前升级到该版本即可。
今天是 2021.01.08,距离 2038 还有 17 年,目前所有在用的 MySQL 版本在 2038 年到来前,都需要进行升级。