如何选择能够适应2038年-滚动的MySQL列数据类型?

如何选择能够适应2038年-滚动的MySQL列数据类型?,mysql,sql,datetime,database-design,year2038,Mysql,Sql,Datetime,Database Design,Year2038,2038年1月19日03:14:07格林尼治标准时间现在离我们不到20年了。这就是UNIX的32位时间戳的滚动时间。我正在设计一些MySQL表,这些表在当时可能仍在使用 这就是所谓的2038年问题 从我在MariaDB 10.3上尝试过的东西来看,使用时间戳数据类型在日期滚动后为日期戳生成错误1292(不正确的日期时间值) 将这些表设计成可供未来使用的良好实践是什么?我可以使用DATETIME数据,但是TIMESTAMP在时区方面有一些非常有用的特性 MySQL的未来版本(更不用说Linux和其

2038年1月19日03:14:07格林尼治标准时间现在离我们不到20年了。这就是UNIX的32位时间戳的滚动时间。我正在设计一些MySQL表,这些表在当时可能仍在使用

这就是所谓的2038年问题

从我在MariaDB 10.3上尝试过的东西来看,使用
时间戳
数据类型在日期滚动后为日期戳生成错误1292(不正确的日期时间值)

将这些表设计成可供未来使用的良好实践是什么?我可以使用
DATETIME
数据,但是
TIMESTAMP
在时区方面有一些非常有用的特性


MySQL的未来版本(更不用说Linux和其他UNIX衍生产品)是否有可能升级?

使用BigInts存储UNIX时间戳。这在功能上等同于时间戳类型,尽管缺少一些附加在时间戳类型上的糖。但是,如果在应用程序级别您乐于使用UNIX时间戳,那么这一点都没有区别,至少到目前为止,对于我来说,在数据库层偶尔使用UNIX_TIMESTAMP(…)/FROM_UNIXTIME(…)调用来处理这一问题是微不足道的。这将使你继续走到2038年以后

尽管我预计MySQL/Maria mob会在X.y版本中创建一些黑客攻击,作为升级路径的一部分自动更新时间戳字段。请注意,它可能会在2038年1月18日发布


不管怎样,如果你想证明未来,BIGINT被当作UNIX时间戳是你的答案。

拿出你在1998年写的代码。找一台机器来运行它。您可能需要找到一个软盘驱动器来加载它

现在,问问自己“20年后代码和硬件会发生什么变化”

我建议,除了政府合同之外,2018年编写的所有代码都将在2038年之前被扔进垃圾桶

1998年,MySQL运行的是3.xx版;我不想用一个10年(或20年)的杆子来碰它。从那时起,
DATETIME
的内部格式发生了变化,添加了
字符集
,添加了大量优化,添加了子查询,修复了bug,等等


我在最后一段中的观点是,随着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_时间戳_fixed('2039-01-01')

返回217749200.000000

select from_unixtime_fixed(2177449200.100000);
返回2039-01-01 00:00:00.100000


如果您对毫秒不感兴趣,请将小数点(16,6)减少为小数点(16,0)

。您的MySQL表仍将被使用,但到MySQL版本20.0时,它们可能会有一个解决此问题的升级路径。您可以始终使用
datetime
并将时区偏移量存储在另一列中。@GordonLinoff您假设OP不存储未来的时间。另外:永远不要存储偏移量,存储奥尔森字符串,如Europe/Amsterdam。@Evert。具有讽刺意味的是,OP并没有要求现在就存储未来的日期。这是一个问题,也是当前的问题。许多金融工具(如美国抵押贷款)在2038年后已经到期。我会使用
DATE
进行抵押,而不是
DATETIME
,也不是
TIMESTAMP
。我不会来处理DATE的问题,当然。但是,
DATETIME
也是未来的证明,它的优点是在使用日期戳算法之前不需要进行转换。Datetime与您关心的32位UNIX时间戳具有相同的上限。很多应用程序可能希望在此之前设置一个日期。甚至不需要在未来20年。只是未来的几年要比2038年他们最终解决这个问题的时间还要长。我也更喜欢实际的时间度量,而不是随着时区的变化而变化的东西。Datetime目前不比Timestamp或32位int UNIX时间更能证明未来。Datetime无法回答您的问题。恕我直言,
Datetime
的范围正好在
10000-01-01
之前。请参阅MySQL 5.5的文档。我的错误。但其余的部分仍然存在。DateTime不是实际的时间值。您询问如何处理MySQL/MariaDB中的2038问题,您不喜欢DateTime,而喜欢时间戳。因此,我给了您一种使用UNIX时间戳的方法,它适用于大多数场景,并且是未来的证明。除非您在数据库中执行大量业务逻辑(糟糕的做法),否则这应该不是什么大问题。无论如何,这就是我给你的答案。
时间戳
会根据客户端的时区自动调整
BIGINT
没有。这一点很好。我在20年前开始编写PHP和MySQL,并经历了许多代码更改以进行升级。一个很好的例子是从mysql到现在使用mysqli或PDO准备好的语句。