Database
 sql >> Database >  >> RDS >> Database

Qual è il problema dell'anno 2038?

Il problema dell'anno 2038 (indicato anche come bug dell'anno 2038) si riferisce a un problema che alcuni sistemi informatici potrebbero incontrare quando si tratta di tempi passati 2038-01-19 03:14:07.

Molti sistemi informatici, come Unix e sistemi basati su Unix, non calcolano il tempo utilizzando il calendario gregoriano. Calcolano il tempo come numero di secondi dal 1 gennaio 1970. Pertanto, in questi sistemi, il tempo è rappresentato come un numero grande (cioè il numero di secondi trascorsi dal 1970-01-01 00:00:00). Questo è in genere indicato come Epoch time, Unix time, Unix Epoch time o POSIX time. Mentre scrivo, l'ora Unix è 1560913841. E mentre scrivo questa riga successiva, l'ora Unix è aumentata a 1560913879.

Il problema 2038 è causato dal fatto che molti sistemi memorizzano questo numero come intero binario a 32 bit con segno. L'intervallo di un numero intero a 32 bit con segno è compreso tra -2.147.483.648 e 2.147.483.647. Ciò significa che l'ultima Epoch time che può essere rappresentata è 2147483647. Ciò avverrà alle 03:14:07 di martedì 19 gennaio 2038.

Successivamente, il risultato dipenderà in gran parte dal sistema. In molti sistemi, si verificherà un overflow di numeri interi e eventuali tempi successivi si avvolgeranno e verranno archiviati internamente come un numero negativo. Il risultato è che un secondo dopo, l'ora sarà interpretata come il 13 dicembre 1901 anziché il 19 gennaio 2038.

Tuttavia, potresti anche ottenere risultati variabili, a seconda dell'applicazione in uso. Anche se il tuo sistema operativo non ha problemi, il tuo codice potrebbe comunque avere problemi. Ad esempio, se hai scritto un codice personalizzato per restituire l'ora Unix e lo memorizzi in un numero intero di 4 byte con segno, avrai problemi. In questi casi, riscrivere il codice per utilizzare un numero intero di 8 byte potrebbe essere tutto ciò che devi fare.

Dato che questo sito web è interamente incentrato sui database, ecco alcuni esempi di database.

Esempio 1 – MySQL

In MySQL, il TIMESTAMP il tipo di dati supporta date/ora da "1970-01-01 00:00:01.000000" UTC a "2038-01-19 03:14:07.999999". Pertanto, puoi dire che qualsiasi database che utilizza questo tipo di dati ha un bug Y2K38.

MySQL ha anche una funzione integrata chiamata UNIX_TIMESTAMP() che, come ci si potrebbe aspettare, restituisce il timestamp Unix.

Il UNIX_TIMESTAMP() accetta un argomento facoltativo che consente di specificare una data da utilizzare per l'ora Unix (ovvero il numero di secondi da "1970-01-01 00:00:00" UTC all'ora specificata). L'intervallo valido dei valori degli argomenti è lo stesso di TIMESTAMP tipo di dati, che va da "1970-01-01 00:00:01.000000" UTC a "2038-01-19 03:14:07.999999" UTC. Se passi una data fuori intervallo a questa funzione, restituisce 0 .

Ecco cosa succede se tenti di utilizzare questa funzione per restituire l'ora Unix da una data successiva a "2038-01-19 03:14:07.999999":

SELECT UNIX_TIMESTAMP('2038-01-20') Result;

Risultato:

+--------+
| Result |
+--------+
|      0 |
+--------+

Otteniamo 0 perché l'argomento della data non rientra nell'intervallo supportato.

Una segnalazione di bug correlata è stata sollevata per il team MySQL nel 2005 (sebbene alcune delle specifiche sembrino essere diverse) e al momento della stesura di questo articolo non è stata ancora affrontata.

Un problema simile è stato sollevato anche per risolvere le limitazioni con il TIMESTAMP tipo di dati, che deve ancora essere affrontato.

Esempio 2:SQL Server

SQL Server non ha attualmente un equivalente di UNIX_TIMESTAMP di MySQL funzione. Pertanto, se devi restituire l'ora di Epoch, dovrai fare qualcosa del genere:

SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE());

Questo va bene per le date precedenti al problema del 2038. Dopo quella data, avrai problemi, perché DATEDIFF() la funzione restituisce il risultato come int tipo di dati. Il int il tipo di dati ha un intervallo compreso tra -2^31 (-2.147.483.648) e 2^31-1 (2.147.483.647).

Ecco cosa succede se provo a restituire Epoch time dopo "2038-01-19 03:14:07":

SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Result';

Risultato:

The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

Fortunatamente, c'è anche un DATEDIFF_BIG() funzione, che fa esattamente la stessa cosa, tranne per il fatto che restituisce il risultato come bigint tipo di dati.

Quindi possiamo riscrivere l'esempio precedente come segue per superare questo problema:

SELECT DATEDIFF_BIG(SECOND,'1970-01-01 00:00:00', '2038-01-19 03:14:08') AS 'Result';

Risultato:

+------------+
| Result     |
|------------|
| 2147483648 |
+------------+

Il grande il tipo di dati utilizza 8 byte (invece di 4 byte per un int ), quindi dovrai decidere se passare o meno a DATEDIFF_BIG() ora o dopo. Se la tua domanda riguarda date future, potrebbe essere prudente farlo prima che dopo.