Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Por que o limite de tempo máximo do MySQL é 838:59:59?


A TIME os valores sempre foram armazenados em 3 bytes no MySQL. Mas o formato mudou na versão 5.6 .4 . Eu suspeito que esta não foi a primeira vez que mudou. Mas a outra mudança, se houve, aconteceu há muito tempo e não há evidência pública disso. O histórico do código-fonte do MySQL no GitHub começa com a versão 5.5 (o commit mais antigo é de maio de 2008), mas a mudança que estou procurando aconteceu por volta de 2001-2002 (o MySQL 4 foi lançado em 2003)

O formato atual, conforme descrito na documentação, usa 6 bits por segundos (valores possíveis:0 para 63 ), 6 bits para minutos, 10 bits para horas (valores possíveis:0 para 1023 ), 1 bit para sinal (somar os valores negativos dos intervalos já mencionados) e 1 bit não utilizado e rotulado como "reservado para futuras extensões".

É otimizado para trabalhar com componentes de tempo (horas, minutos, segundos) e não desperdiça muito espaço. Usando este formato é possível armazenar valores entre -1023:59:59 e +1023:59:59 . No entanto, o MySQL limita o número de horas para 838 , provavelmente para compatibilidade com aplicativos que foram escritos há algum tempo, quando acho que esse era o limite.

Até a versão 5.6.4, o TIME os valores também foram armazenados em 3 bytes e os componentes foram empacotados como days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds . Esse formato foi otimizado para trabalhar com timestamps (porque era, na verdade, um timestamp). Usando este formato, seria possível armazenar valores no intervalo de cerca de -2330 para +2330 horas. Apesar de ter esse grande intervalo de valores disponível, o MySQL ainda estava limitando os valores a -838 para +838 horas.

Houve bug #11655 no MySQL 4. Foi possível retornar TIME valores fora do -838..+838 intervalo usando SELECT aninhado declarações. Não era um recurso, mas um bug e foi corrigido.

A única razão para limitar os valores a esse intervalo e alterar ativamente qualquer parte do código que produz TIME valores fora dele era compatibilidade com versões anteriores.

Suspeito que o MySQL 3 tenha usado um formato diferente que, devido à forma como os dados foram compactados, limitou os valores válidos ao intervalo -838..+838 horas.

Ao olhar para o atual código-fonte do MySQL Encontrei esta fórmula interessante:
#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + TIME_MAX_SECOND)

Vamos ignorar por enquanto o MAX parte dos nomes usados ​​acima e vamos lembrar apenas que TIME_MAX_MINUTE e TIME_MAX_SECOND são números entre 00 e 59 . A fórmula apenas concatena as horas, minutos e segundos em um único número inteiro. Por exemplo, o valor 170:29:45 torna-se 1702945 .

Esta fórmula levanta a seguinte questão:dado que o TIME os valores são armazenados em 3 bytes com sinal, qual é o valor máximo positivo que pode ser representado desta forma?

O valor que estamos procurando é 0x7FFFFF que em notação decimal é 8388607 . Desde os últimos quatro dígitos (8607 ) deve ser lido como minutos (86 ) e segundos (07 ) e seus valores máximos válidos são 59 , o maior valor que pode ser armazenado em 3 bytes com sinal usando a fórmula acima é 8385959 . Que, como TIME é +838:59:59 . Ta-da!

Adivinha? O fragmento de C o código listado acima foi extraído disso:
/* 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)

Tenho certeza de que é assim que o MySQL 3 costumava manter o TIME valores internamente. Esse formato impôs a limitação do intervalo e o requisito de compatibilidade com versões anteriores nas versões subsequentes propagou a limitação até nossos dias.