Database
 sql >> Datenbank >  >> RDS >> Database

Was ist das Jahr-2038-Problem?

Das Jahr-2038-Problem (auch als Y2K38-Bug bezeichnet) bezieht sich auf ein Problem, auf das einige Computersysteme stoßen können, wenn sie mit Zeiten nach 2038-01-19 03:14:07 umgehen.

Viele Computersysteme, wie Unix und Unix-basierte Systeme, berechnen die Zeit nicht mit dem gregorianischen Kalender. Sie berechnen die Zeit als die Anzahl der Sekunden seit dem 1. Januar 1970. Daher wird die Zeit in diesen Systemen als große Zahl dargestellt (d. h. die Anzahl der Sekunden, die seit dem 01.01.1970 00:00:00 vergangen sind). Dies wird typischerweise als Epochenzeit, Unix-Zeit, Unix-Epochenzeit oder POSIX-Zeit bezeichnet. Während ich dies schreibe, ist die Unix-Zeit 1560913841. Und während ich diese nächste Zeile schreibe, hat sich die Unix-Zeit auf 1560913879 erhöht.

Das 2038-Problem wird dadurch verursacht, dass viele Systeme diese Zahl als vorzeichenbehaftete binäre 32-Bit-Ganzzahl speichern. Der Bereich einer vorzeichenbehafteten 32-Bit-Ganzzahl ist -2.147.483.648 bis 2.147.483.647. Dies bedeutet, dass die späteste Epochenzeit, die dargestellt werden kann, 2147483647 ist. Dies wird am Dienstag, den 19. Januar 2038 um 03:14:07 Uhr auftreten.

Danach hängt das Ergebnis weitgehend vom System ab. In vielen Systemen tritt ein ganzzahliger Überlauf auf, und alle späteren Zeiten werden umlaufen und intern als negative Zahl gespeichert. Das Ergebnis ist, dass eine Sekunde später die Uhrzeit als 13. Dezember 1901 und nicht als 19. Januar 2038 interpretiert wird.

Je nach verwendeter Anwendung können Sie jedoch auch zu unterschiedlichen Ergebnissen kommen. Selbst wenn Ihr Betriebssystem kein Problem hat, könnte Ihr eigener Code immer noch ein Problem haben. Wenn Sie beispielsweise benutzerdefinierten Code geschrieben haben, um die Unix-Zeit zurückzugeben, und Sie ihn in einer vorzeichenbehafteten 4-Byte-Ganzzahl speichern, werden Sie Probleme bekommen. In solchen Fällen reicht es möglicherweise aus, den Code so umzuschreiben, dass er eine 8-Byte-Ganzzahl verwendet.

Da sich auf dieser Website alles um Datenbanken dreht, finden Sie hier einige Datenbankbeispiele.

Beispiel 1 – MySQL

In MySQL der TIMESTAMP Der Datentyp unterstützt Daten/Zeiten von „1970-01-01 00:00:01.000000“ UTC bis „2038-01-19 03:14:07.999999“. Daher könnte man sagen, dass jede Datenbank, die diesen Datentyp verwendet, einen Y2K38-Fehler hat.

MySQL hat auch eine eingebaute Funktion namens UNIX_TIMESTAMP() was, wie zu erwarten, den Unix-Zeitstempel zurückgibt.

Der UNIX_TIMESTAMP() -Funktion akzeptiert ein optionales Argument, mit dem Sie ein Datum angeben können, das für die Unix-Zeit verwendet werden soll (d. h. die Anzahl der Sekunden von „1970-01-01 00:00:00“ UTC bis zu der von Ihnen angegebenen Zeit). Der gültige Bereich der Argumentwerte ist derselbe wie für TIMESTAMP Datentyp, der „1970-01-01 00:00:01.000000“ UTC bis „2038-01-19 03:14:07.999999“ UTC ist. Wenn Sie dieser Funktion ein Datum außerhalb des Bereichs übergeben, gibt sie 0 zurück .

Folgendes passiert, wenn Sie versuchen, diese Funktion zu verwenden, um die Unix-Zeit von einem Datum nach „2038-01-19 03:14:07.999999“ zurückzugeben:

SELECT UNIX_TIMESTAMP('2038-01-20') Result;

Ergebnis:

+--------+
| Result |
+--------+
|      0 |
+--------+

Wir erhalten 0 da das Datumsargument außerhalb des unterstützten Bereichs liegt.

Ein verwandter Fehlerbericht wurde 2005 für das MySQL-Team erstellt (obwohl einige der Besonderheiten anders zu sein scheinen) und zum jetzigen Zeitpunkt immer noch nicht behandelt.

Ein ähnliches Problem wurde auch angesprochen, um die Einschränkungen mit dem TIMESTAMP zu beheben Datentyp, der ebenfalls noch angesprochen werden muss.

Beispiel 2 – SQL-Server

SQL Server hat derzeit kein Äquivalent zu UNIX_TIMESTAMP von MySQL Funktion. Wenn Sie also die Epochenzeit zurückgeben müssen, müssen Sie so etwas tun:

SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE());

Dies ist für Daten vor dem 2038-Problem in Ordnung. Nach diesem Datum treten Probleme auf, da DATEDIFF() Funktion gibt das Ergebnis als int zurück Datentyp. Der int Datentyp hat einen Bereich von -2^31 (-2.147.483.648) bis 2^31-1 (2.147.483.647).

Folgendes passiert, wenn ich versuche, die Epochenzeit nach „2038-01-19 03:14:07“ zurückzugeben:

SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Result';

Ergebnis:

The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

Glücklicherweise gibt es auch ein DATEDIFF_BIG() Funktion, die genau das Gleiche tut, außer dass sie das Ergebnis als bigint zurückgibt Datentyp.

Wir können also das vorherige Beispiel wie folgt umschreiben, um dieses Problem zu lösen:

SELECT DATEDIFF_BIG(SECOND,'1970-01-01 00:00:00', '2038-01-19 03:14:08') AS 'Result';

Ergebnis:

+------------+
| Result     |
|------------|
| 2147483648 |
+------------+

Die Bigint Datentyp verwendet 8 Bytes (im Gegensatz zu 4 Bytes für ein int ), also müssen Sie entscheiden, ob Sie zu DATEDIFF_BIG() wechseln möchten oder nicht jetzt oder später. Wenn sich Ihre Bewerbung auf zukünftige Daten bezieht, ist es möglicherweise ratsam, dies früher als später zu tun.