当前位置:  开发笔记 > 编程语言 > 正文

PHP和mySQL:2038年错误:它是什么?怎么解决?

如何解决《PHP和mySQL:2038年错误:它是什么?怎么解决?》经验,为你挑选了3个好方法。

我正在考虑使用TIMESTAMP存储日期+时间,但我读到它有2038年的限制.我没有大量提出我的问题,而是倾向于将其分解成小部分,以便新手用户也能轻松理解.所以我的问题:

    2038年的问题究竟是什么?

    它为什么会发生?当它发生时会发生什么?

    我们如何解决它?

    是否有任何可能的替代方案使用它,这不会造成类似的问题?

    当真正发生时,我们可以对使用TIMESTAMP的现有应用程序做些什么来避免所谓的问题?

提前致谢.



1> Corey Ballou..:

我已将此标记为社区维基,因此您可以随意编辑.

2038年的问题究竟是什么?

"2038年的问题(也称为Unix Millennium Bug,Y2K38类似于Y2K问题)可能会导致某些计算机软件在2038年之前或之后失败.该问题影响所有将系统时间存储为签名的软件和系统32 -bit integer,并将此数字解释为1970年1月1日00:00:00 UTC以来的秒数."


它为什么会发生?当它发生时会发生什么?

超越时代3时14分07秒UTC在星期二,2038 1月19日将"环绕"并为负数,这些系统将在1901年12月13日,解释为一个时间,而不是在2038年内部存储这是由于事实上,自UNIX纪元(1970年1月1日00:00:00 GMT)以来的秒数将超过计算机32位有符号整数的最大值.


我们如何解决它?

使用长数据类型(64位就足够了)

对于MySQL(或MariaDB),如果您不需要时间信息,请考虑使用DATE列类型.如果您需要更高的准确度,请使用DATETIME而不是TIMESTAMP.请注意,DATETIME列不存储有关时区的信息,因此您的应用程序必须知道使用了哪个时区.

Wikipedia上描述的其他可能的解决方案

等待MySQL开发人员修复十年前报告的这个错误.


是否有任何可能的替代方案使用它,这不会造成类似的问题?

尽可能尝试使用大型类型在数据库中存储日期:64位就足够了 - GNU C和POSIX/SuS中的long long类型,或sprintf('%u'...)PHP或BCmath扩展中的long long类型.


即使我们还没有在2038年,有哪些可能会破坏用例?

因此,MySQL DATETIME的范围为1000-9999,但TIMESTAMP的范围仅为1970-2038.如果您的系统存储了生日,未来的转发日期(例如30年抵押贷款)或类似情况,那么您已经遇到了这个错误.同样,如果这是一个问题,请不要使用TIMESTAMP.


当真正发生时,我们可以对使用TIMESTAMP的现有应用程序做些什么来避免所谓的问题?

很少有PHP应用程序在2038年仍然存在,但很难预见,因为网络还不是传统平台.

以下是更改要转换TIMESTAMP为的数据库表列的过程DATETIME.它首先创建一个临时列:

# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;

# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;

# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);

# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`

资源

2038年问题(维基百科)

互联网将在30年内结束


在MySQL中,如果将来的版本将TIMESTAMP的基础存储数据类型更改为64位,那么就不需要将代码更改为DATETIME,对吧?我只是不认为任何人使用TIMESTAMP都是不对的,因为数据类型确实有它的目的.
MySQL(和MariaDB)不使用64位整数在64位系统上存储时间戳是绝对荒谬的.使用DATETIME**不是一个合适的解决方案,因为我们不知道时区.这是[2005年回归报道](https://bugs.mysql.com/bug.php?id=12654),但仍无法修复.
真棒.对我来说,你的答案是最完整的.非常感谢.

2> Pascal MARTI..:

使用UNIX时间戳存储日期时,实际上使用的是32位整数,它保留自1970-01-01以来的秒数; 看Unix时间

这个32位数将在2038年溢出.这就是2038年的问题.


要解决该问题,您不能使用32位UNIX时间戳来存储日期 - 这意味着,在使用MySQL时,您不应该使用TIMESTAMP,但是DATETIME(参见10.3.1.DATETIME,DATE和TIMESTAMP类型):

DATETIME当您需要包含日期和时间信息的值时,将使用该类型.支持的范围是'1000-01-01 00:00:00''9999-12-31 23:59:59'.

TIMESTAMP数据类型的范围为'1970-01-01 00:00:01'UTC到 '2038-01-19 03:14:07'UTC.


您可以对应用程序执行以避免/修复该问题 的(可能)最好的事情是不使用TIMESTAMP,但DATETIME对于必须包含不在1970年和2038年之间的日期的列.

但是有一个小小的说明:从2038年开始,你的应用程序可能已被重写了很多次(从统计学上来说)非常高^ ^所以也许,如果你不需要在未来处理日期,您不必在当前版本的应用程序中处理该问题...



3> Rubens Faria..:

快速搜索Google就可以解决问题:2038年问题

    2038年的问题(也称为Unix Millennium Bug,Y2K38类似于Y2K问题)可能会导致某些计算机软件在2038年之前或之后失败

    该问题会影响将系统时间存储为带符号的32位整数的所有软件和系统,并将此数字解释为自1970年1月1日00:00:00 UTC以来的秒数.可以通过这种方式表示的最新时间是在2038年1月19日星期二03:14:07 UTC.超越这一时刻的时间将"环绕"并在内部存储为负数,这些系统将在1901年而不是2038年解释为日期

    对于现有CPU/OS组合,现有文件系统或现有二进制数据格式,此问题没有简单的解决方法

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有