Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dlaczego maksymalny limit czasu MySQL wynosi 838:59:59?

TIME wartości były zawsze przechowywane na 3 bajtach w MySQL. Ale format zmienił się w wersji 5.6 .4 . Podejrzewam, że to nie był pierwszy raz, kiedy to się zmieniło. Ale druga zmiana, jeśli była, miała miejsce dawno temu i nie ma na to publicznych dowodów. Historia kodu źródłowego MySQL na GitHub zaczyna się od wersji 5.5 (najstarsze zatwierdzenie pochodzi z maja 2008 r.), ale zmiana, której szukam, nastąpiła gdzieś w okolicach 2001-2002 (MySQL 4 został uruchomiony w 2003 r.)

Obecny format, zgodnie z opisem w dokumentacji, używa 6 bitów na sekundy (możliwe wartości:0 do 63 ), 6 bitów na minuty, 10 bitów na godziny (możliwe wartości:0 do 1023 ), 1 bit na znak (dodaj ujemne wartości wspomnianych już przedziałów) i 1 bit jest nieużywany i oznaczony jako „zarezerwowany na przyszłe rozszerzenia”.

Jest zoptymalizowany do pracy ze składnikami czasu (godziny, minuty, sekundy) i nie marnuje dużo miejsca. Przy użyciu tego formatu można przechowywać wartości między -1023:59:59 i +1023:59:59 . Jednak MySQL ogranicza liczbę godzin do 838 , prawdopodobnie dla wstecznej kompatybilności z aplikacjami, które zostały napisane jakiś czas temu, kiedy myślę, że to był limit.

Do wersji 5.6.4 TIME wartości były również przechowywane na 3 bajtach, a komponenty były pakowane jako days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Ten format został zoptymalizowany do pracy ze znacznikami czasu (ponieważ w rzeczywistości był to znacznik czasu). Używając tego formatu, można by przechowywać wartości z zakresu około -2330 do +2330 godziny. Mając tak duży zakres dostępnych wartości, MySQL wciąż ograniczał wartości do -838 do +838 godziny.

Wystąpił błąd #11655 na MySQL 4. Można było zwrócić TIME wartości poza -838..+838 zakres przy użyciu zagnieżdżonego SELECT sprawozdania. To nie była funkcja, ale błąd i został naprawiony.

Jedynym powodem, aby ograniczyć wartości do tego zakresu i aktywnie zmieniać dowolny fragment kodu, który generuje TIME wartości poza nią były zgodne z poprzednimi wersjami.

Podejrzewam, że MySQL 3 używał innego formatu, który ze względu na sposób pakowania danych ograniczył prawidłowe wartości do zakresu -838..+838 godzin.

Patrząc na aktualny kod źródłowy MySQL Znalazłem tę ciekawą formułę:

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

Na razie zignorujmy MAX część nazw użytych powyżej i pamiętajmy tylko, że TIME_MAX_MINUTE i TIME_MAX_SECOND to liczby od 00 i 59 . Formuła po prostu łączy godziny, minuty i sekundy w jedną liczbę całkowitą. Na przykład wartość 170:29:45 staje się 1702945 .

Ta formuła rodzi następujące pytanie:biorąc pod uwagę, że TIME wartości są przechowywane na 3 bajtach ze znakiem, jaka jest maksymalna dodatnia wartość, którą można przedstawić w ten sposób?

Szukana przez nas wartość to 0x7FFFFF że w notacji dziesiętnej jest 8388607 . Od ostatnich czterech cyfr (8607 ) należy odczytywać jako minuty (86 ) i sekund (07 ), a ich maksymalne poprawne wartości to 59 , największa wartość, która może być przechowywana na 3 bajtach ze znakiem przy użyciu powyższej formuły to 8385959 . Które, jak TIME to +838:59:59 . Ta-da!

Zgadnij co? Fragment C kod wymieniony powyżej został wyodrębniony z tego:

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

Jestem pewien, że w ten sposób MySQL 3 utrzymywał TIME wartości wewnętrznie. Ten format narzucił ograniczenie zakresu, a wymóg kompatybilności wstecznej w kolejnych wersjach rozpropagował to ograniczenie do naszych czasów.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Policz liczbę unikalnych wartości

  2. Jak skopiować bazę danych SQLite z Androida do bazy danych MySQL (replikacja/synchronizacja)

  3. Unikalne ograniczenie, które pozwala na puste wartości w MySQL

  4. Zoptymalizuj wydajność zapisu dla instancji AWS Aurora

  5. Zaktualizuj tabelę mysql za pomocą zapytania wybierającego z innej bazy danych