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


116

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

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

미리 감사드립니다.


1
아직 28 년이 남았습니다. 1982 년부터 컴퓨터 관련 기술을 사용하고 계십니까? 있을 것 같지 않게. 그러니 걱정하지 마세요. 2038 년이되면 더 이상 문제가되지 않을 것입니다.
Gordon

24
고든, 나는 예측을하는 애플리케이션을 만든다. 나는 매달 얼마나 많은 돈을 저축하고 언제 백만장자가 될지 예측할 수 있습니다. 제 경우에는 28 년이 그다지 많지 않으며, 지금이 문제가있는 유일한 사람은 저뿐이 아닙니다 (타임 스탬프를 나타내는 64 비트 숫자를 사용하여 해결했습니다).
Emil Vikström 2010 년

2
@Emil 지금 64 비트 정수를 사용하여 구체적인 문제에 대한 쉬운 해결책을 찾았습니다. 모든 사람에게 적용되지는 않지만 (또는 필요로하는) ​​유스 케이스를 위해 작동합니다. 요점은 OP에 예측과 같은 구체적인 문제가 없으면 흥미로운 주제 일 수 있지만 일반적인 수준에서이 문제를 해결하는 것은 PHP (태그에주의) 문제가 아니기 때문에 걱정할 필요가 없다는 것입니다. 내 2c.
Gordon

1
2038 년까지 "YYYY-MM-DD HH : MM : SS : mmmm ..."문자열을 구문 분석하는 것이 가장 저렴한 작업이 될 것입니다. 2038 년까지 32 비트는 폐기 될 것입니다. 나는 그때 존재할 것이라는 것을 알고있는 유닉스 타임 스탬프가 의심스럽고 만약 그렇다면 우리의 256 비트 시스템은 4096 비트 시스템이 행복한 식사로 제공되는 시대를 훨씬 넘어서는 날짜를 처리 할 것입니다.
Super Cat

8
9 년이 지난 지금 고든. TIMESTAMPS는 계속 사용됩니다. 우리는 28 년 전의 기술을 여전히 사용합니다. 월드 와이드 웹이라고합니다.
sfscs 19

답변:


149

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

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`

자원


2
대박. 나에게 당신의 대답은 가장 완벽합니다. 고맙습니다.
Devner 2010 년

7
MySQL에서 향후 버전이 TIMESTAMP의 기본 스토리지 데이터 유형을 64 비트로 변경하면 코드를 DATETIME으로 변경할 필요가 없습니다. TIMESTAMP를 사용하지 못하게하는 것은 그 데이터 유형에 목적이 있기 때문에 옳은 일이라고 생각하지 않습니다.
pixelfreak

1
MySQL의 서명 된 BIGINT 필드는 타임 스탬프를 저장하는 데 잘 작동하는 것처럼 보이며 MySQL 5.5에서 일부 로컬 테스트를 수행하여 작동하는지 확인했습니다. 과거의 날짜도 나타낼 수 있으므로 서명을 사용하는 것이 서명되지 않은 것보다 낫습니다. 타임 스탬프에 BIGINT를 사용하지 않는 이유가 있습니까?
zuallauz

한 가지 주목할 점은 MySQL은 타임 스탬프 필드에 대해 현재 날짜 / 시간 (CURRENT_TIMESTAMP)으로 만 자동 설정됩니다. 이 기능이 결국 모든 날짜 유형으로 이식되기를 바랍니다.
Ray

5
MySQL (및 MariaDB)이 64 비트 시스템에 타임 스탬프를 저장하기 위해 64 비트 정수를 사용하지 않는 것은 절대적으로 터무니없는 일입니다. 시간대에 대해 모르기 때문에 DATETIME을 사용 하는 것은 적절한 해결책 이 아닙니다 . 이것은 2005 년보고 되었지만 여전히 수정 사항이 없습니다.
마이크

14

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 년 이전에 신청서가 꽤 많이 다시 작성 될 가능성이 매우 높습니다 (통계적으로 말하면) ^^ 그러니 미래의 날짜를 다룰 필요가 없다면 , 현재 버전의 응용 프로그램에서 해당 문제를 처리 할 필요가 없습니다.


1
+1 정보. 여기서 시도는 처음부터 모범 사례를 적용하여 나중에 문제에 대해 걱정할 필요가 없도록하는 것입니다. 따라서 지금은 2038 년이 문제가 아닌 것 같지만 모범 사례를 따르고 처음부터 내가 만드는 모든 응용 프로그램에 대해 따르고 싶습니다. 이해가 되길 바랍니다.
Devner 2010 년

예, 말이됩니다. 요점을 알겠습니다. 그러나 "모범 사례"는 "요구에 대한 답변"을 의미 할 수도 있습니다. 타임 스탬프가 충분하다는 것을 알고 있다면 datetime을 사용할 필요가 없습니다 (예를 들어 저장하기 위해 더 많은 메모리가 필요합니다. 수백만 개의 레코드가 있습니다) ;; 일부 열 (예 : 현재 날짜를 포함하는 열)에 타임 스탬프를 사용하고 다른 열 (예 : 과거 / 미래 날짜를 포함하는 열)에는 datetime을 사용하는 애플리케이션이 있습니다.
Pascal MARTIN

귀하의 절차도 의미가 있으며 특히 저장 공간과 관련하여 잘 작동합니다. 괜찮다면 애플리케이션의 TIMESTAMP 열에 일반적으로 사용하는 구조와 길이를 물어봐도 될까요? 감사.
Devner 2010 년

글쎄요, 제가 TIMESTAMP를 사용하고 싶을 때, 그것은 내 "날짜 / 시간"데이터가 1970 년에서 2038 년 사이에 적합하기 때문입니다. 그래서 저는 MySQL TIMESTAMP 데이터 유형을 사용합니다.
Pascal MARTIN

정보 주셔서 감사합니다. 귀하의 답변에 따르면 열을 TIMESTAMP로 선언하는 것으로 충분하며 길이를 제공하지 않는 int 또는 var와 달리 길이를 제공 할 필요가 없음을 이해합니다. 내가 맞아?
Devner 2010 년

7

구글에서 빠른 검색이 트릭을 할 것입니다 : 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 조합, 기존 파일 시스템 또는 기존 바이너리 데이터 형식에 대한이 문제를 쉽게 해결할 수있는 방법은 없습니다.

2

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 참조 !!! ;)


귀하의 포인트 4 및 5는 '참조로 전화'를 상기시킵니다. 그것은 내 얼굴에 미소를 지었다. 감사합니다. +1.
Devner 2010 년

1

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

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

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


-1

아무것도 업그레이드하고 싶지 않았기 때문에 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'];

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.