sql >> Database >  >> RDS >> Mysql

Waarom is de maximale tijdslimiet van MySQL 838:59:59?

De TIME waarden werden altijd opgeslagen op 3 bytes in MySQL. Maar de indeling is gewijzigd op versie 5.6 .4 . Ik vermoed dat dit niet de eerste keer was dat het veranderde. Maar de andere verandering, als die er was, is lang geleden gebeurd en er is geen openbaar bewijs van. De geschiedenis van de MySQL-broncode op GitHub begint met versie 5.5 (de oudste commit is van mei 2008) maar de verandering waarnaar ik op zoek ben, gebeurde ergens rond 2001-2002 (MySQL 4 werd gelanceerd in 2003)

Het huidige formaat, zoals beschreven in de documentatie, gebruikt 6 bits voor seconden (mogelijke waarden:0 tot 63 ), 6 bits voor minuten, 10 bits voor uren (mogelijke waarden:0 tot 1023 ), 1 bit voor teken (voeg de negatieve waarden van de reeds genoemde intervallen toe) en 1 bit is ongebruikt en heeft het label "gereserveerd voor toekomstige extensies".

Het is geoptimaliseerd voor het werken met tijdcomponenten (uren, minuten, seconden) en verspilt niet veel ruimte. Met dit formaat is het mogelijk om waarden op te slaan tussen -1023:59:59 en +1023:59:59 . MySQL beperkt het aantal uren echter tot 838 , waarschijnlijk voor achterwaartse compatibiliteit met applicaties die een tijdje geleden zijn geschreven, terwijl ik denk dat dit de limiet was.

Tot versie 5.6.4, de TIME waarden werden ook opgeslagen op 3 bytes en de componenten werden verpakt als days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Dit formaat is geoptimaliseerd voor het werken met tijdstempels (omdat het in feite een tijdstempel was). Met dit formaat zou het mogelijk zijn om waarden op te slaan in het bereik van ongeveer -2330 tot +2330 uur. Hoewel dit grote bereik aan waarden beschikbaar was, beperkte MySQL de waarden nog steeds tot -838 tot +838 uur.

Er was bug #11655 op MySQL 4. Het was mogelijk om TIME te retourneren waarden buiten de -838..+838 bereik met behulp van geneste SELECT verklaringen. Het was geen functie maar een bug en het is opgelost.

De enige reden om de waarden te beperken tot dit bereik en om elk stukje code actief te wijzigen dat TIME produceert waarden daarbuiten was achterwaartse compatibiliteit.

Ik vermoed dat MySQL 3 een ander formaat gebruikte dat, vanwege de manier waarop de gegevens waren verpakt, de geldige waarden beperkte tot het bereik -838..+838 uur.

Door te kijken naar de huidige broncode van MySQL Ik vond deze interessante formule:

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

Laten we de MAX . voorlopig negeren een deel van de hierboven gebruikte namen en laten we alleen die TIME_MAX_MINUTE . onthouden en TIME_MAX_SECOND zijn getallen tussen 00 en 59 . De formule voegt alleen de uren, minuten en seconden samen in één geheel getal. Bijvoorbeeld de waarde 170:29:45 wordt 1702945 .

Deze formule roept de volgende vraag op:aangezien de TIME waarden worden opgeslagen op 3 bytes met teken, wat is de maximale positieve waarde die op deze manier kan worden weergegeven?

De waarde die we zoeken is 0x7FFFFF dat in decimale notatie is 8388607 . Sinds de laatste vier cijfers (8607 ) moet worden gelezen als minuten (86 ) en seconden (07 ) en hun maximale geldige waarden zijn 59 , de grootste waarde die kan worden opgeslagen op 3 bytes met teken met behulp van de bovenstaande formule is 8385959 . Wat, als TIME is +838:59:59 . Ta-da!

Raad eens? Het fragment van C bovenstaande code is hieruit geëxtraheerd:

/* 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)

Ik weet zeker dat dit is hoe MySQL 3 de TIME . bijhield waarden intern. Dit formaat legde de beperking van het bereik op, en de eis van achterwaartse compatibiliteit voor de volgende versies verspreidde de beperking tot onze dagen.



  1. Querygroep repareren met only_full_group_by

  2. listunagg functie?

  3. NEXT_DAY() Functie in Oracle

  4. Een PHP MYSQL-rangschikkingsquery krijgen om te rangschikken op basis van de totale som van de score