PHP & mySQL: Jahr 2038 Fehler: Was ist das? Wie man es löst?

115

Ich habe darüber nachgedacht, TIMESTAMP zum Speichern von Datum und Uhrzeit zu verwenden, aber ich habe gelesen, dass es eine Beschränkung für das Jahr 2038 gibt. Anstatt meine Frage in großen Mengen zu stellen, habe ich es vorgezogen, sie in kleine Teile aufzuteilen, damit sie auch für Anfänger leicht verständlich sind. Also meine Frage (n):

  1. Was genau ist das Problem des Jahres 2038?
  2. Warum tritt es auf und was passiert, wenn es auftritt?
  3. Wie lösen wir das?
  4. Gibt es mögliche Alternativen zur Verwendung, die kein ähnliches Problem darstellen?
  5. Was können wir mit den vorhandenen Anwendungen tun, die TIMESTAMP verwenden, um das sogenannte Problem zu vermeiden, wenn es tatsächlich auftritt?

Danke im Voraus.

Devner
quelle
1
Das sind noch 28 Jahre. Verwenden Sie noch Computertechnologie aus dem Jahr 1982? Unwahrscheinlich. Machen Sie sich also keine Sorgen, denn bis 2038 wird es wahrscheinlich kein Problem mehr geben.
Gordon
24
Gordon, ich mache eine Anwendung, die Prognosen erstellt. Ich spare, wie viel Geld ich jeden Monat habe, und kann dann schätzen, wann ich Millionär werde. In meinem Fall sind 28 Jahre nicht so viel, und ich bin sicher, dass ich nicht der einzige bin, der dieses Problem derzeit hat (ich habe es gelöst, indem ich 64-Bit-Zahlen zur Darstellung des Zeitstempels verwendet habe).
Emil Vikström
2
@Emil von 64 - Bit - Integer mit gerade jetzt , haben Sie sich eine einfache Lösung zu einem konkreten Problem gefunden. Gilt nicht für alle (oder wird von allen benötigt), arbeitet aber für Ihren Anwendungsfall. Der Punkt ist, wenn das OP kein konkretes Problem wie die Prognose hat, dann ist dies möglicherweise ein interessantes Thema, aber nichts, worüber er sich Sorgen machen sollte, da das Lösen dieses Problems auf allgemeiner Ebene kein PHP-Problem (Mind the Tag) ist. Nur mein 2c.
Gordon
1
Bis 2038 wird das Parsen der Zeichenfolge "JJJJ-MM-TT HH: MM: SS: mmmm ..." die billigste Operation sein, von der Sie träumen können. Bis 2038 werden 32 Bit veraltet sein. Ich bezweifle, dass der Unix-Zeitstempel, wie wir ihn kennen, dann existieren wird, und wenn dies der Fall ist, werden unsere 256-Bit-Systeme Daten verarbeiten, die weit über das Alter hinausgehen, in dem 4096-Bit-Systeme in fröhlichen Mahlzeiten ausgegeben werden.
Super Cat
8
Gordon, es ist jetzt 9 Jahre später. TIMESTAMPS werden weiterhin verwendet. Wir verwenden immer noch Technologie von vor 28 Jahren. Es heißt World Wide Web.
sfscs

Antworten:

149

Ich habe dies als Community-Wiki markiert. Sie können es also nach Belieben bearbeiten.

Was genau ist das Problem des Jahres 2038?

"Das Problem des Jahres 2038 (analog zum Y2K-Problem auch als Unix Millennium Bug, Y2K38 bekannt) kann dazu führen, dass einige Computersoftware vor oder im Jahr 2038 ausfällt. Das Problem betrifft alle Software und Systeme, in denen die Systemzeit als signierte 32 gespeichert ist -bit Ganzzahl, und interpretieren Sie diese Zahl als die Anzahl der Sekunden seit 00:00:00 UTC am 1. Januar 1970. "


Warum tritt es auf und was passiert, wenn es auftritt?

Zeiten jenseits 03:14:07 UTC am Dienstag, 19. Januar 2038, werden " umlaufen " und intern als negative Zahl gespeichert, die diese Systeme als Zeit am 13. Dezember 1901 und nicht im Jahr 2038 interpretieren. Dies ist darauf zurückzuführen Die Tatsache, dass die Anzahl der Sekunden seit der UNIX-Epoche (1. Januar 1970, 00:00:00 GMT) den Maximalwert eines Computers für eine 32-Bit-Ganzzahl mit Vorzeichen überschritten hat.


Wie lösen wir das?

  • Verwenden Sie lange Datentypen (64 Bit sind ausreichend)
  • Wenn Sie für MySQL (oder MariaDB) keine Zeitinformationen benötigen, sollten Sie den DATESpaltentyp verwenden. Wenn Sie eine höhere Genauigkeit benötigen, verwenden Sie DATETIMEstatt TIMESTAMP. Beachten Sie, dass in DATETIMESpalten keine Informationen zur Zeitzone gespeichert werden, sodass Ihre Anwendung wissen muss, welche Zeitzone verwendet wurde.
  • Andere mögliche Lösungen auf Wikipedia beschrieben
  • Warten Sie, bis MySQL-Entwickler diesen vor über einem Jahrzehnt gemeldeten Fehler behoben haben.

Gibt es mögliche Alternativen zur Verwendung, die kein ähnliches Problem darstellen?

Versuchen Sie nach Möglichkeit, große Typen zum Speichern von Daten in Datenbanken zu verwenden: 64-Bit ist ausreichend - ein langer langer Typ in GNU C und POSIX / SuS oder sprintf('%u'...) in PHP oder der BCmath-Erweiterung.


Was sind einige potenziell brechende Anwendungsfälle, obwohl wir noch nicht im Jahr 2038 sind?

Ein MySQL DATETIME hat also einen Bereich von 1000-9999, aber TIMESTAMP hat nur einen Bereich von 1970-2038. Wenn Ihr System Geburtsdaten, zukünftige Termine (z. B. 30-jährige Hypotheken) oder ähnliches speichert, wird dieser Fehler bereits auftreten. Verwenden Sie auch hier nicht TIMESTAMP, wenn dies ein Problem darstellen soll.


Was können wir mit den vorhandenen Anwendungen tun, die TIMESTAMP verwenden, um das sogenannte Problem zu vermeiden, wenn es tatsächlich auftritt?

Im Jahr 2038 werden es nur noch wenige PHP-Anwendungen geben, obwohl dies schwer vorhersehbar ist, da das Web noch kaum eine Legacy-Plattform ist.

Hier ist ein Prozess zum Ändern einer Datenbanktabellenspalte, in die konvertiert werden TIMESTAMPsoll DATETIME. Es beginnt mit dem Erstellen einer temporären Spalte:

# 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`

Ressourcen

Corey Ballou
quelle
2
Genial. Für mich ist Ihre Antwort die vollständigste. Vielen Dank.
Devner
7
Wenn in MySQL die zukünftige Version den zugrunde liegenden Speicherdatentyp von TIMESTAMP in 64-Bit ändert, müssen Sie Ihren Code nicht in DATETIME ändern, oder? Ich denke einfach nicht, dass es richtig ist, jemanden davon abzuhalten, TIMESTAMP zu verwenden, da dieser Datentyp seinen Zweck hat.
Pixelfreak
1
Das signierte BIGINT- Feld von MySQL scheint gut zum Speichern von Zeitstempeln zu funktionieren, und ich habe einige lokale Tests mit MySQL 5.5 durchgeführt, die bestätigen, dass es funktioniert. Offensichtlich wäre die Verwendung von signiert besser als nicht signiert, da Sie auch Daten in der Vergangenheit darstellen können. Gibt es einen Grund, BIGINT nicht für Zeitstempel zu verwenden?
zuallauz
Zu beachten ist, dass MySQL für Zeitstempelfelder nur automatisch auf das aktuelle Datum / die aktuelle Uhrzeit (CURRENT_TIMESTAMP) eingestellt wird. Hoffentlich wird diese Funktionalität irgendwann auf alle Datumstypen portiert.
Ray
5
Es ist absolut absurd, dass MySQL (und MariaDB) keine 64-Bit-Ganzzahlen verwenden, um Zeitstempel auf 64-Bit-Systemen zu speichern. Die Verwendung von DATETIME ist keine adäquate Lösung, da wir keine Ahnung von der Zeitzone haben. Dies wurde bereits 2005 gemeldet , es ist jedoch noch kein Fix verfügbar.
Mike
14

Wenn Sie UNIX-Zeitstempel zum Speichern von Datumsangaben verwenden, verwenden Sie tatsächlich 32-Bit-Ganzzahlen, die die Anzahl der Sekunden seit dem 01.01.1970 zählen. Siehe Unix-Zeit

Diese 32-Bit-Zahl wird 2038 überlaufen. Das ist das 2038-Problem.


Um dieses Problem zu lösen, dürfen Sie zum Speichern Ihrer Daten keinen 32-Bit-UNIX-Zeitstempel verwenden. Wenn Sie also MySQL verwenden, sollten Sie nicht verwenden TIMESTAMP, aber DATETIME(siehe 10.3.1. Die Typen DATETIME, DATE und TIMESTAMP ):

Der DATETIMETyp wird verwendet, wenn Sie Werte benötigen, die sowohl Datums- als auch Zeitinformationen enthalten. Der unterstützte Bereich ist '1000-01-01 00:00:00'zu '9999-12-31 23:59:59' .

Der TIMESTAMPDatentyp hat einen Bereich von '1970-01-01 00:00:01'UTC bis '2038-01-19 03:14:07'UTC.


Das (wahrscheinlich) Beste, was Sie mit Ihrer Anwendung tun können, um dieses Problem zu vermeiden / zu beheben, ist, es nicht zu verwenden TIMESTAMP, aberDATETIME für die Spalten, die Daten enthalten müssen, die nicht zwischen 1970 und 2038 liegen.

Ein kleiner Hinweis: Es gibt eine sehr hohe Wahrscheinlichkeit (statistisch gesehen), dass Ihre Bewerbung vor 2038 einige Male neu geschrieben wurde ^^ Vielleicht also, wenn Sie sich in Zukunft nicht mit Daten befassen müssen müssen Sie sich mit der aktuellen Version Ihrer Anwendung nicht um dieses Problem kümmern ...

Pascal MARTIN
quelle
1
+1 Für die Info. Hier wird versucht, Best Practices von Anfang an anzupassen, damit Sie sich später nicht mehr um das Problem kümmern müssen. Obwohl 2038 im Moment nicht nach einem Problem klingt, möchte ich nur die Best Practices befolgen und sie von Anfang an für jede von mir erstellte Anwendung befolgen. Hoffe das macht Sinn.
Devner
Ja, es macht Sinn, ich verstehe Ihren Standpunkt. "Best Practice" kann aber auch bedeuten, "was den Bedarf erfüllt" - Wenn Sie wissen, dass ein Zeitstempel ausreicht, müssen Sie keine Datums- / Uhrzeitangabe verwenden (diese benötigen beispielsweise mehr Speicher, um gespeichert zu werden; und das kann von Bedeutung sein, wenn Sie haben Millionen von Datensätzen) ;; Ich habe einige Anwendungen, in denen ich Zeitstempel für einige Spalten verwende (Spalten, die beispielsweise das aktuelle Datum enthalten), und Datums- und Uhrzeitangaben für einige andere (Spalten, die beispielsweise vergangene / zukünftige Daten enthalten)
Pascal MARTIN
Ich sehe, dass Ihr Verfahren auch Sinn macht und gut funktioniert, insbesondere wenn es um Speicherplatz geht. Wenn es in Ordnung ist, darf ich Sie fragen, welche Struktur und Länge Sie allgemein für die TIMESTAMP-Spalte in Ihren Anwendungen verwenden? Vielen Dank.
Devner
Wenn ich einen TIMESTAMP verwenden möchte, ist dies für /, weil meine "Datum / Uhrzeit" -Daten zwischen 1970 und 2038 passen - und daher verwende ich den Datentyp MySQL TIMESTAMP.
Pascal MARTIN
Danke für die Information. Aus Ihrer Antwort geht hervor, dass es ausreicht, die Spalte nur als TIMESTAMP zu deklarieren, und wir müssen keine Länge dafür angeben (im Gegensatz zu und int oder var, wo wir die Länge angeben). Habe ich recht?
Devner
7

Eine schnelle Suche bei Google reicht aus: Problem Jahr 2038

  1. Das Problem des Jahres 2038 (in Analogie zum Y2K-Problem auch als Unix Millennium Bug, Y2K38 bekannt) kann dazu führen, dass einige Computersoftware vor oder im Jahr 2038 ausfällt
  2. Das Problem betrifft alle Software und Systeme, die die Systemzeit als vorzeichenbehaftete 32-Bit-Ganzzahl speichern und diese Zahl als die Anzahl der Sekunden seit 00:00:00 UTC am 1. Januar 1970 interpretieren. Die späteste Zeit, die auf diese Weise dargestellt werden kann ist 03:14:07 UTC am Dienstag, 19. Januar 2038. Zeiten, die über diesen Moment hinausgehen, werden "umlaufen" und intern als negative Zahl gespeichert, die diese Systeme als Datum im Jahr 1901 und nicht im Jahr 2038 interpretieren
  3. Es gibt keine einfache Lösung für dieses Problem für vorhandene CPU / OS-Kombinationen, vorhandene Dateisysteme oder vorhandene binäre Datenformate
Rubens Farias
quelle
2

http://en.wikipedia.org/wiki/Year_2038_problem enthält die meisten Details

Zusammenfassend:

1) + 2) Das Problem ist, dass viele Systeme Datumsinformationen als 32-Bit-Int mit Vorzeichen speichern, was der Anzahl der Sekunden seit dem 1.1.1970 entspricht. Das letzte Datum, das so gespeichert werden kann, ist 03:14:07 UTC am Dienstag, den 19. Januar 2038. In diesem Fall wird der int "umbrochen" und als negative Zahl gespeichert, die als Datum im Jahr 1901 interpretiert wird. Was genau dann passieren wird, variiert von System zu System, aber es reicht zu sagen, dass es wahrscheinlich für keinen von ihnen gut sein wird!

Für Systeme, die nur Daten in der Vergangenheit speichern, müssen Sie sich wohl eine Weile keine Sorgen machen! Das Hauptproblem sind Systeme, die in Zukunft mit Daten arbeiten. Wenn Ihr System in 28 Jahren mit Daten arbeiten muss, sollten Sie sich jetzt Sorgen machen!

3) Verwenden Sie eines der verfügbaren alternativen Datumsformate oder wechseln Sie zu einem 64-Bit-System und verwenden Sie 64-Bit-Ints. Oder verwenden Sie für Datenbanken ein alternatives Zeitstempelformat (z. B. für MySQL verwenden Sie DATETIME).

4) Siehe 3!

5) Siehe 4 !!! ;)

Addsy
quelle
Ihre Punkte 4 und 5 erinnern mich an "Call by Reference". Das brachte ein Lächeln auf mein Gesicht. Danke & +1 für das gleiche.
Devner
1

Bros, wenn Sie PHP zum Anzeigen von Zeitstempeln verwenden müssen, ist dies die BESTE PHP-Lösung, ohne vom UNIX_TIMESTAMP-Format zu wechseln.

Verwenden Sie eine custom_date () -Funktion. Verwenden Sie darin die DateTime. Hier ist die DateTime-Lösung .

Solange Sie UNSIGNED BIGINT (8) als Zeitstempel in der Datenbank haben. Solange Sie PHP 5.2.0 ++ haben

Dexter
quelle
-1

Da ich nichts aktualisieren wollte, bat ich mein Backend (MSSQL), diesen Job anstelle von PHP zu erledigen!

$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);

echo $row_tmp['next_date'];

Vielleicht kein effizienter Weg, aber es funktioniert.

Venkatesh GS Rao
quelle