[php] PHP 및 mySQL : 2038 년 버그 : 무엇입니까? 그것을 해결하는 방법?

TIMESTAMP를 사용하여 날짜 + 시간을 저장하려고 생각했지만 2038 년 제한이 있다는 것을 읽었습니다. 대량으로 질문하는 대신 초보 사용자도 쉽게 이해할 수 있도록 작은 부분으로 나누는 것을 선호했습니다. 그래서 내 질문 (들) :

  1. 2038 년 문제는 정확히 무엇입니까?
  2. 왜 발생하고 발생하면 어떻게됩니까?
  3. 어떻게 해결합니까?
  4. 비슷한 문제를 일으키지 않는 사용에 대한 가능한 대안이 있습니까?
  5. TIMESTAMP를 사용하는 기존 애플리케이션에 대해 소위 문제가 실제로 발생하는 것을 방지하기 위해 무엇을 할 수 있습니까?

미리 감사드립니다.



답변

나는 이것을 커뮤니티 위키로 표시 했으므로 편하게 편집 할 수 있습니다.

2038 년 문제는 정확히 무엇입니까?

“2038 년 문제 (Y2K 문제와 유사하게 Unix Millennium Bug, Y2K38라고도 함)로 인해 일부 컴퓨터 소프트웨어가 2038 년 이전 또는 2038 년에 실패 할 수 있습니다.이 문제는 시스템 시간을 서명 된 32로 저장하는 모든 소프트웨어 및 시스템에 영향을줍니다. -비트 정수이고이 숫자를 1970 년 1 월 1 일 00:00:00 UTC 이후의 초 수로 해석합니다. “


왜 발생하고 발생하면 어떻게됩니까?

2038 년 1 월 19 일 화요일 03:14:07 UTC 이후의 시간 은 ‘ 순환 ‘되어 내부적으로 음수로 저장되며, 이러한 시스템은 2038 년이 아닌 1901 년 12 월 13 일의 시간으로 해석됩니다. UNIX 시대 (1970 년 1 월 1 일 00:00:00 GMT) 이후의 시간 (초)이 32 비트 부호있는 정수에 대한 컴퓨터의 최대 값을 초과했다는 사실.


어떻게 해결합니까?

  • 긴 데이터 유형 사용 (64 비트이면 충분 함)
  • MySQL (또는 MariaDB)의 경우 시간 정보가 필요하지 않으면 DATE열 유형을 사용하는 것이 좋습니다. 더 높은 정확도가 필요한 DATETIME경우 TIMESTAMP. 조심하십시오 DATETIME응용 프로그램이 사용 된 시간대 알고 있어야합니다, 그래서 열이 시간대에 대한 정보를 저장하지 않습니다.
  • Wikipedia에 설명 된 다른 가능한 솔루션
  • MySQL 개발자가 10 년 전에보고 된 이 버그 를 수정할 때까지 기다리십시오 .

비슷한 문제를 일으키지 않는 사용에 대한 가능한 대안이 있습니까?

데이터베이스에 날짜를 저장하기 위해 가능한 한 큰 유형을 사용하도록 시도하십시오. 64 비트이면 충분합니다. GNU C 및 POSIX / SuS 또는 sprintf('%u'...)PHP 또는 BCmath 확장 의 long long 유형입니다 .


아직 2038 년이 아니지만 잠재적으로 파괴되는 사용 사례에는 어떤 것이 있습니까?

따라서 MySQL DATETIME 의 범위는 1000-9999이지만 TIMESTAMP의 범위는 1970-2038입니다. 시스템에 생년월일, 미래의 미래 날짜 (예 : 30 년 모기지) 또는 이와 유사한 정보가 저장되어 있으면 이미이 버그가 발생합니다. 다시 말하지만 이것이 문제가 될 경우 TIMESTAMP를 사용하지 마십시오.


TIMESTAMP를 사용하는 기존 애플리케이션에 대해 소위 문제가 실제로 발생하는 것을 방지하기 위해 무엇을 할 수 있습니까?

웹이 아직 레거시 플랫폼이 아니기 때문에 예측하기는 어렵지만 2038 년에는 PHP 애플리케이션이 거의 없을 것입니다.

다음은 변환 TIMESTAMP할 데이터베이스 테이블 열을 변경하는 프로세스입니다 DATETIME. 임시 열을 만드는 것으로 시작합니다.

# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;

# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;

# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);

# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`

자원


답변

UNIX 타임 스탬프를 사용하여 날짜를 저장할 때 실제로는 1970-01-01 이후의 초 수를 유지하는 32 비트 정수를 사용합니다. Unix Time 참조

그 32 비트 숫자는 2038 년에 넘칠 것입니다. 이것이 2038 년 문제입니다.

이 문제를 해결하기 위해, 당신은 당신의 날짜 저장하는 데 32 개 비트를 UNIX 타임 스탬프를 사용해서는 안 – 수단, MySQL을 사용하는 경우, 당신은 사용하지 말아야 TIMESTAMP하지만 DATETIME(참조 10.3.1을 DATETIME, DATE, 및 TIMESTAMP 유형. )

DATETIME유형은 날짜 및 시간 정보를 모두 포함하는 값이 필요할 때 사용됩니다. 지원되는 범위는 '1000-01-01 00:00:00'~
'9999-12-31 23:59:59'입니다.

TIMESTAMP데이터 유형의 범위가 '1970-01-01 00:00:01'에 UTC
'2038-01-19 03:14:07'UTC합니다.

(아마도) 이 문제는 사용하지 않는 것을 피하기 / 수정하는 응용 프로그램에 할 수있는 가장 좋은 방법 TIMESTAMP,하지만 DATETIME1970 년과 2038 사이에없는 날짜를 포함해야하는 열의.

하지만 한 가지 작은 메모 : 2038 년 이전에 신청서가 꽤 많이 다시 작성 될 가능성이 매우 높습니다 (통계적으로 말하면) ^^ 그러니 미래의 날짜를 다룰 필요가 없다면 , 현재 버전의 응용 프로그램에서 해당 문제를 처리 할 필요가 없습니다.


답변

구글에서 빠른 검색이 트릭을 할 것입니다 : 2038 년 문제

  1. 2038 년 문제 (Y2K 문제와 유사하게 Unix Millennium Bug, Y2K38라고도 함)로 인해 일부 컴퓨터 소프트웨어가 2038 년 이전 또는 이후에 실패 할 수 있습니다.
  2. 이 문제는 시스템 시간을 부호있는 32 비트 정수로 저장하는 모든 소프트웨어 및 시스템에 영향을 미치며이 숫자를 1970 년 1 월 1 일 00:00:00 UTC 이후의 초 수로 해석합니다. 이러한 방식으로 표현할 수있는 최신 시간 2038 년 1 월 19 일 화요일 03:14:07 UTC입니다.이 순간 이후의 시간은 “둘러싸고”내부적으로 음수로 저장됩니다.이 시스템은 2038 년이 아닌 1901 년의 날짜로 해석됩니다.
  3. 기존 CPU / OS 조합, 기존 파일 시스템 또는 기존 바이너리 데이터 형식에 대한이 문제를 쉽게 해결할 수있는 방법은 없습니다.

답변

http://en.wikipedia.org/wiki/Year_2038_problem 에 대부분의 세부 정보가 있습니다.

요약해서 말하자면:

1) + 2) 문제는 많은 시스템이 1970 년 1 월 1 일 이후의 초 수와 동일한 32 비트 부호있는 정수로 날짜 정보를 저장한다는 것입니다. 이와 같이 저장 될 수있는 최신 날짜는 2038 년 1 월 19 일 화요일 03:14:07 UTC입니다.이 경우 int는 “둘러싸고”음수로 저장되며 1901 년 날짜로 해석됩니다. 정확히 무슨 일이 일어날 지, 시스템마다 다르지만 아마 그들 중 누구에게도 좋지 않을 것이라고 말하기에 충분합니다!

과거의 날짜 만 저장하는 시스템의 경우 잠시 걱정할 필요가 없습니다! 주요 문제는 미래의 날짜로 작동하는 시스템에 있습니다. 시스템이 28 년 후의 날짜로 작동해야한다면 지금 걱정해야합니다!

3) 사용 가능한 대체 날짜 형식 중 하나를 사용하거나 64 비트 시스템으로 이동하고 64 비트 정수를 사용합니다. 또는 데이터베이스의 경우 대체 타임 스탬프 형식을 사용합니다 (예 : MySQL의 경우 DATETIME 사용).

4) 3을보십시오!

5) 4 참조 !!! 😉


답변

브라더스, PHP를 사용하여 타임 스탬프를 표시해야하는 경우 UNIX_TIMESTAMP 형식을 변경하지 않고 최고의 PHP 솔루션입니다.

custom_date () 함수를 사용하십시오. 그 안에 DateTime을 사용하십시오. 다음은 DateTime 솔루션 입니다.

데이터베이스의 타임 스탬프로 UNSIGNED BIGINT (8)가있는 한. PHP 5.2.0 ++이있는 한


답변

아무것도 업그레이드하고 싶지 않았기 때문에 PHP 대신이 작업을 수행하도록 백엔드 (MSSQL)에 요청했습니다!

$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);

echo $row_tmp['next_date'];

효율적인 방법은 아니지만 작동합니다.


답변