sql >> Base de Datos >  >> RDS >> Mysql

¿Por qué el límite de tiempo máximo de MySQL es 838:59:59?

El TIME los valores siempre se almacenaron en 3 bytes en MySQL. Pero el formato cambió en versión 5.6 .4 . Sospecho que no fue la primera vez que cambió. Pero el otro cambio, si lo hubo, ocurrió hace mucho tiempo y no hay evidencia pública de ello. El historial del código fuente de MySQL en GitHub comienza con la versión 5.5 (la confirmación más antigua es de mayo de 2008), pero el cambio que busco ocurrió entre 2001 y 2002 (MySQL 4 se lanzó en 2003)

El formato actual, como se describe en la documentación, usa 6 bits por segundos (valores posibles:0 a 63 ), 6 bits para minutos, 10 bits para horas (valores posibles:0 a 1023 ), 1 bit por signo (agregue los valores negativos de los intervalos ya mencionados) y 1 bit está sin usar y está etiquetado como "reservado para futuras extensiones".

Está optimizado para trabajar con componentes de tiempo (horas, minutos, segundos) y no desperdicia mucho espacio. Usando este formato es posible almacenar valores entre -1023:59:59 y +1023:59:59 . Sin embargo, MySQL limita el número de horas a 838 , probablemente por compatibilidad con versiones anteriores de aplicaciones que se escribieron hace un tiempo, cuando creo que este era el límite.

Hasta la versión 5.6.4, el TIME los valores también se almacenaron en 3 bytes y los componentes se empaquetaron como days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Este formato se optimizó para trabajar con marcas de tiempo (porque, de hecho, era una marca de tiempo). Usando este formato sería posible almacenar valores en el rango de alrededor de -2330 a +2330 horas. Aunque tenía esta gran variedad de valores disponibles, MySQL seguía limitando los valores a -838 al +838 horas.

Hubo error #11655 en MySQL 4. Era posible devolver TIME valores fuera del -838..+838 rango usando SELECT anidado declaraciones. No era una función sino un error y se solucionó.

La única razón para limitar los valores a este rango y cambiar activamente cualquier pieza de código que produzca TIME valores fuera de él era compatibilidad con versiones anteriores.

Sospecho que MySQL 3 usó un formato diferente que, debido a la forma en que se empaquetaron los datos, limitó los valores válidos al rango -838..+838 horas.

Examinando el código fuente de MySQL Encontré esta fórmula interesante:

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

Ignoremos por el momento el MAX parte de los nombres usados ​​arriba y recordemos solo que TIME_MAX_MINUTE y TIME_MAX_SECOND son números entre 00 y 59 . La fórmula simplemente concatena las horas, los minutos y los segundos en un solo número entero. Por ejemplo, el valor 170:29:45 se convierte en 1702945 .

Esta fórmula plantea la siguiente pregunta:dado que el TIME los valores se almacenan en 3 bytes con signo, ¿cuál es el valor positivo máximo que se puede representar de esta manera?

El valor que buscamos es 0x7FFFFF que en notación decimal es 8388607 . Desde los últimos cuatro dígitos (8607 ) debe leerse como minutos (86 ) y segundos (07 ) y sus valores máximos válidos son 59 , el mayor valor que se puede almacenar en 3 bytes con signo usando la fórmula anterior es 8385959 . Que, como TIME es +838:59:59 . ¡Ta-da!

¿Adivina qué? El fragmento de C El código mencionado anteriormente se extrajo de esto:

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

Estoy seguro de que así es como MySQL 3 solía mantener el TIME valores internamente. Este formato impuso la limitación del rango, y el requisito de compatibilidad con versiones anteriores en las versiones posteriores propagó la limitación hasta nuestros días.