TIME стойностите винаги се съхраняват на 3 байта в MySQL. Но форматът се промени на версия 5.6 .4
. Подозирам, че това не беше първият път, когато се промени. Но другата промяна, ако е имало такава, се е случила отдавна и няма публични доказателства за нея. Историята на изходния код на MySQL в GitHub започва с версия 5.5 (най-старият комит е от май 2008 г.), но промяната, която търся, се случи някъде около 2001-2002 г. (MySQL 4 беше пуснат през 2003 г.)
Текущият формат, както е описано в документацията, използва 6 бита за секунди (възможни стойности:0 до 63 ), 6 бита за минути, 10 бита за часове (възможни стойности:0 до 1023 ), 1 бит за знак (добавете отрицателните стойности на вече споменатите интервали) и 1 бит е неизползван и е обозначен като „резервиран за бъдещи разширения“.
Оптимизиран е за работа с времеви компоненти (часове, минути, секунди) и не губи много място. Използвайки този формат, е възможно да съхранявате стойности между -1023:59:59 и +1023:59:59 . Въпреки това MySQL ограничава броя часове до 838 , вероятно за обратна съвместимост с приложения, които бяха написани преди време, когато мисля, че това беше границата.
До версия 5.6.4, TIME стойностите също бяха съхранени на 3 байта и компонентите бяха опаковани като days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Този формат беше оптимизиран за работа с времеви печати (защото всъщност беше времеви печат). Използването на този формат би било възможно да се съхраняват стойности в диапазона от около -2330 до +2330 часа. Въпреки че разполагаше с този голям диапазон от стойности, MySQL все още ограничаваше стойностите до -838 до +838 часа.
Имаше бъг №11655
на MySQL 4. Беше възможно да се върне TIME стойности извън -838..+838 диапазон с помощта на вложен SELECT изявления. Това не беше функция, а грешка и беше отстранена.
Единствената причина да ограничите стойностите до този диапазон и активно да промените всяка част от кода, която произвежда TIME стойности извън него беше обратна съвместимост.
Подозирам, че MySQL 3 използва различен формат, който поради начина, по който данните бяха опаковани, ограничи валидните стойности до диапазона -838..+838 часа.
Като разгледате текущия изходния код на MySQL Намерих тази интересна формула:
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)
Нека игнорираме за момента MAX част от използваните по-горе имена и нека запомним само това TIME_MAX_MINUTE и TIME_MAX_SECOND са числа между 00 и 59 . Формулата просто обединява часовете, минутите и секундите в едно цяло число. Например стойността 170:29:45 става 1702945 .
Тази формула повдига следния въпрос:като се има предвид, че TIME Стойностите се съхраняват на 3 байта със знак, каква е максималната положителна стойност, която може да бъде представена по този начин?
Стойността, която търсим, е 0x7FFFFF това в десетичния запис е 8388607 . Тъй като последните четири цифри (8607 ) трябва да се чете като минути (86). ) и секунди (07). ) и техните максимални валидни стойности са 59 , най-голямата стойност, която може да бъде съхранена на 3 байта със знак, като се използва формулата по-горе, е 8385959 . Което, като TIME е +838:59:59 . Та-да!
Познай какво? Фрагментът на C кодът, изброен по-горе, е извлечен от това:
/* 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)
Сигурен съм, че това е начинът, по който MySQL 3 използваше TIME вътрешно ценности. Този формат наложи ограничението на обхвата, а изискването за обратна съвместимост на следващите версии разпространи ограничението до наши дни.