Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum ist das maximale Zeitlimit von MySQL 838:59:59?

Die TIME Werte wurden in MySQL immer auf 3 Bytes gespeichert. Aber das Format hat sich in Version 5.6 geändert .4 . Ich vermute, dass dies nicht das erste Mal war, dass es sich geändert hat. Aber die andere Veränderung, falls es eine gab, ist vor langer Zeit passiert und es gibt keinen öffentlichen Beweis dafür. Der Verlauf des MySQL-Quellcodes auf GitHub beginnt mit Version 5.5 (der älteste Commit stammt vom Mai 2008), aber die Änderung, nach der ich suche, geschah irgendwo zwischen 2001 und 2002 (MySQL 4 wurde 2003 eingeführt)

Das aktuelle Format, wie in der Dokumentation beschrieben, verwendet 6 Bits für Sekunden (mögliche Werte:0 bis 63 ), 6 Bit für Minuten, 10 Bit für Stunden (mögliche Werte:0 bis 1023 ), 1 Bit für Vorzeichen (addieren Sie die negativen Werte der bereits erwähnten Intervalle) und 1 Bit ist unbenutzt und mit "reserviert für zukünftige Erweiterungen" gekennzeichnet.

Es ist für die Arbeit mit Zeitkomponenten (Stunden, Minuten, Sekunden) optimiert und verschwendet nicht viel Platz. Mit diesem Format ist es möglich, Werte zwischen -1023:59:59 zu speichern und +1023:59:59 . Allerdings begrenzt MySQL die Anzahl der Stunden auf 838 , wahrscheinlich aus Gründen der Abwärtskompatibilität mit Anwendungen, die vor einiger Zeit geschrieben wurden, als ich denke, dass dies die Grenze war.

Bis Version 5.6.4 ist die TIME Werte wurden auch auf 3 Bytes gespeichert und die Komponenten wurden als days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds gepackt . Dieses Format wurde für die Arbeit mit Zeitstempeln optimiert (weil es tatsächlich ein Zeitstempel war). Mit diesem Format wäre es möglich, Werte im Bereich von etwa -2330 zu speichern an +2330 Std. Obwohl dieser große Wertebereich verfügbar war, beschränkte MySQL die Werte immer noch auf -838 an +838 Std.

Es gab Bug #11655 auf MySQL 4. Es war möglich, TIME zurückzugeben Werte außerhalb von -838..+838 Bereich mit verschachteltem SELECT Aussagen. Es war kein Feature, sondern ein Fehler, der behoben wurde.

Der einzige Grund, die Werte auf diesen Bereich zu beschränken und aktiv jeden Code zu ändern, der TIME erzeugt Werte außerhalb davon war Abwärtskompatibilität.

Ich vermute, dass MySQL 3 ein anderes Format verwendet hat, das aufgrund der Art und Weise, wie die Daten gepackt wurden, die gültigen Werte auf den Bereich -838..+838 beschränkte Stunden.

Durch einen Blick in den aktuellen Quellcode von MySQL Ich habe diese interessante Formel gefunden:

#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)

Lassen Sie uns für den Moment das MAX ignorieren Teil der oben verwendeten Namen und erinnern wir uns nur an diese TIME_MAX_MINUTE und TIME_MAX_SECOND sind Zahlen zwischen 00 und 59 . Die Formel verkettet einfach die Stunden, Minuten und Sekunden in einer einzigen Ganzzahl. Zum Beispiel der Wert 170:29:45 wird zu 1702945 .

Diese Formel wirft folgende Frage auf:Da die TIME Werte werden auf 3 Bytes mit Vorzeichen gespeichert, was ist der maximale positive Wert, der auf diese Weise dargestellt werden kann?

Der gesuchte Wert ist 0x7FFFFF das ist in Dezimalschreibweise 8388607 . Da die letzten vier Ziffern (8607 ) sollte als Minuten gelesen werden (86 ) und Sekunden (07 ) und ihr maximal gültiger Wert ist 59 , ist der größte Wert, der auf 3 Bytes mit Vorzeichen unter Verwendung der obigen Formel gespeichert werden kann, 8385959 . Welche, als TIME ist +838:59:59 . Ta-da!

Erraten Sie, was? Das Fragment von C Der oben aufgeführte Code wurde daraus extrahiert:

/* Limits for the TIME data type */
#define TIME_MAX_HOUR 838
#define TIME_MAX_MINUTE 59
#define TIME_MAX_SECOND 59
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)

Ich bin mir sicher, dass MySQL 3 auf diese Weise die TIME beibehalten hat Werte intern. Dieses Format führte zu einer Beschränkung des Bereichs, und die Abwärtskompatibilitätsanforderung für die nachfolgenden Versionen propagierte die Beschränkung bis in unsere Tage.