2038 年 1 月 19 日 03:14:07 现在距离 GMT 还不到 20 年。这就是 UNIX 的 32 位时间戳翻转的时间。我正在设计一些当时可能仍在使用的 MySQL 表。
这就是所谓的2038年问题。
从我在 MariaDB 10.3 上尝试过的内容看来,使用
TIMESTAMP
数据类型会在日期翻转后为日期戳产生错误 1292(不正确的日期时间值)。
设计这些表格以适应未来的良好做法是什么?我可以使用
DATETIME
数据,但是 TIMESTAMP
在时区方面有一些非常有用的功能。
MySQL 的未来版本(更不用说 Linux 和其他 UNIX 衍生版本)是否有可能升级?
使用 BigInts 存储 unix 时间戳。这在功能上等同于 TIMESTAMP 类型,尽管缺少一些附加的糖分。但是,如果在应用程序级别您愿意只使用 UNIX 时间戳,那么它根本没有区别,并且至少对我来说到目前为止,在数据库层处理偶尔的 UNIX_TIMESTAMP(…) / FROM_UNIXTIME( …) 称呼。这将使您在 2038 年之后走得更远。
虽然我预计 MySQL / Maria 暴民会在 X.y 版本中创建一些 hack,作为升级路径的一部分,它会自动更新时间戳字段。请注意,它可能会在 2038 年 1 月 18 日发布。 ;)
无论如何,如果您想面向未来,将 BIGINT 视为 UNIX 时间戳就是您的答案。
拿出你在 1998 年写的代码。找一台机器来运行它。您可能需要找到软盘驱动器来加载它。
现在,问问自己“20 年后代码和硬件会发生什么”?
我建议,除了政府合同之外,2018 年编写的所有代码早在 2038 年之前就将被扔进垃圾箱。
1998年,MySQL运行版本3.xx;我不想用 10 年(或 20 年)的杆子来触及这个问题。从那时起,
DATETIME
的内部格式发生了变化,添加了CHARACTER SETs
,添加了很多优化,添加了子查询,修复了错误等等。
我在最后一段中的观点是,无论你今天写的是什么,都将随着 MySQL 在未来 20 年的成熟而经历“应用”变化。解决 2038 年问题只是众多改变之一。
CREATE FUNCTION from_unixtime_fixed (v DECIMAL(16,6))
RETURNS DATETIME(6) DETERMINISTIC
RETURN DATE_ADD(FROM_UNIXTIME(0), INTERVAL v second);
CREATE FUNCTION unix_timestamp_fixed (v DATETIME(6))
RETURNS DECIMAL(16,6) DETERMINISTIC
RETURN TIMESTAMPDIFF(SECOND, FROM_UNIXTIME(0), v);
使用示例: 选择 unix_timestamp_fixed('2039-01-01');
返回2177449200.000000
select from_unixtime_fixed(2177449200.100000);
返回2039-01-01 00:00:00.100000
如果您对毫秒不感兴趣,请将 DECIMAL(16,6) 减少为 DECIMAL(16,0)