PHP & MYSQL : 2038 년 버그 : 무엇입니까? 그것을 해결하는 방법?
문제
TimeStamp를 사용하여 날짜+시간을 저장하려고 생각했지만 2038 년의 제한이 있다는 것을 읽었습니다. 내 질문을 대량으로 요구하는 대신, 초보자 사용자도 쉽게 이해할 수 있도록 작은 부품으로 분해하는 것을 선호했습니다. 그래서 내 질문 :
- 2038 년 문제는 정확히 무엇입니까?
- 왜 발생하고 발생하면 어떻게됩니까?
- 우리는 그것을 어떻게 해결합니까?
- 비슷한 문제를 일으키지 않는 사용에 대한 가능한 대안이 있습니까?
- 실제로 발생하는 문제를 피하기 위해 타임 스탬프를 사용하는 기존 응용 프로그램에 무엇을 할 수 있습니까?
미리 감사드립니다.
해결책
나는 이것을 커뮤니티 위키로 표시 했으므로 여가에서 자유롭게 편집하십시오.
2038 년 문제는 정확히 무엇입니까?
"2038 년 문제 (유닉스 밀레니엄 버그라고도 함, Y2K 문제와 유사하게 Y2K38) 일부 컴퓨터 소프트웨어가 2038 년 전 또는 해에 실패 할 수 있습니다.이 문제는 시스템 시간을 서명 한 32로 저장하는 모든 소프트웨어 및 시스템에 영향을 미칩니다. -정수를 비우고 1970 년 1 월 1 일에 00:00:00 UTC 이후 몇 초로 해석하십시오. "
왜 발생하고 발생하면 어떻게됩니까?
너머의 시간 03:14:07 2038 년 1 월 19 일 화요일 UTC 이 시스템은 1901 년 12 월 13 일에 2038 년이 아닌 시간으로 해석 할 '랩 랩 (whal and the the the the)'이라는 마이너스로 저장 될 것입니다. 이는 UNIX Epoch 이후 몇 초가 있다는 사실 때문입니다 (1 월 1 일. 1970 00:00:00 GMT)는 32 비트 서명 정수에 대한 컴퓨터의 최대 값을 초과했습니다.
우리는 그것을 어떻게 해결합니까?
- 긴 데이터 유형 사용 (64 비트가 충분합니다)
- MySQL (또는 mariadb)의 경우 시간 정보가 필요하지 않은 경우 사용을 고려하십시오.
DATE
열 유형. 더 높은 정확도가 필요한 경우 사용하십시오DATETIME
보다는TIMESTAMP
. 조심하십시오DATETIME
열은 시간대에 대한 정보를 저장하지 않으므로 응용 프로그램은 어떤 시간대를 사용했는지 알아야합니다. - Wikipedia에 설명 된 다른 가능한 솔루션
- MySQL Devs가 수정 될 때까지 기다리십시오 이 버그 10 년 전에보고했습니다.
비슷한 문제를 일으키지 않는 사용에 대한 가능한 대안이 있습니까?
데이터베이스에 날짜를 저장하기 위해 대형 유형을 사용할 수있는 곳을 시도해보십시오. 64 비트는 충분합니다 - GNU C 및 POSIX/SUS의 긴 긴 유형입니다. sprintf('%u'...)
PHP 또는 BCMATH 확장에서.
우리가 아직 2038 년에 있지 않더라도 잠재적으로 잠재적으로 사용되는 유스 케이스는 무엇입니까?
그래서 MySQL 날짜 시간 범위는 1000-9999이지만 타임 스탬프의 범위는 1970-2038입니다. 시스템이 생년월일을 저장하거나 미래의 전진 날짜 (예 : 30 년 모기지) 또는 이와 유사한 경우 이미이 버그가 발생할 것입니다. 다시 말하지만, 이것이 문제가 될 경우 타임 스탬프를 사용하지 마십시오.
실제로 발생하는 문제를 피하기 위해 타임 스탬프를 사용하는 기존 응용 프로그램에 무엇을 할 수 있습니까?
Web은 아직 레거시 플랫폼이 아니기 때문에 PHP 응용 프로그램이 여전히 2038 년에 남아있을 것입니다.
다음은 변환 할 데이터베이스 테이블 열을 변경하는 프로세스입니다. 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 타임 스탬프를 사용하여 날짜를 저장하는 경우 실제로는 32 비트 정수를 사용하여 1970-01-01 이후 몇 초를 유지합니다. 보다 유닉스 시간
32 비트 수는 2038 년에 넘쳐납니다. 이것이 2038 문제입니다.
이 문제를 해결하려면 날짜를 저장하기 위해 32 비트 UNIX 타임 스탬프를 사용해서는 안됩니다. 즉, MySQL을 사용할 때는 사용하지 않아야합니다. TIMESTAMP
, 하지만 DATETIME
(보다 10.3.1. DateTime, 날짜 및 타임 스탬프 유형) :
그만큼
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
, 하지만 DATETIME
1970 년에서 2038 년 사이가 아닌 날짜를 포함 해야하는 열의 경우.
그래도 하나의 작은 메모 : 아마도 매우 높을 것입니다. (통계적으로 말하면) 2038 년 전에 신청서가 꽤 많이 다시 작성되었을 것입니다. 귀하의 신청서의 ...
Google의 빠른 검색은 다음을 수행합니다. 2038 년 문제
- 2038 년 문제 (Y2K 문제와 유사하게 Unix Millennium Bug, Y2K38이라고도 함)는 일부 컴퓨터 소프트웨어가 2038 년 전 또는 해에 실패 할 수 있습니다.
- 이 문제는 시스템 시간을 서명 된 32 비트 정수로 저장하는 모든 소프트웨어 및 시스템에 영향을 미치고이 숫자가 1970 년 1 월 1 일 00:00:00 UTC 이후 몇 초로 해석합니다.이 방법으로 표현할 수있는 최신 시간. 2038 년 1 월 19 일 화요일에 UTC는 03:14:07 UTC입니다.이 순간을 넘어서는 시간을 넘어서서 내부적으로 마이너스 숫자로 저장 될 것입니다.
- 기존 CPU/OS 조합, 기존 파일 시스템 또는 기존 바이너리 데이터 형식에 대한이 문제에 대한 쉬운 수정은 없습니다.
http://en.wikipedia.org/wiki/year_2038_problem 대부분의 세부 사항이 있습니다
요약해서 말하자면:
1) + 2) 문제는 많은 시스템이 1970 년 1 월 1 일 이후 초 수와 동일한 32 비트 로그인 된 int로 날짜 정보를 저장한다는 것입니다. 이와 같이 저장할 수있는 최신 날짜는 2038 년 1 월 19 일 화요일에 03:14:07 UTC입니다. 이런 일이 발생하면 int는 "포장"되어 1901 년에 날짜로 해석 될 음수로 저장됩니다. 정확히 일어날 일은 시스템마다 다르지만 아마도 그것들 중 어느 누구에게도 좋지 않을 것이라고 말하면 충분합니다!
과거의 날짜 만 저장하는 시스템의 경우 한동안 걱정할 필요가 없다고 생각합니다! 주요 문제는 향후 날짜와 함께 작동하는 시스템에 관한 것입니다. 시스템이 앞으로 28 년 동안 날짜로 작업해야한다면 지금 걱정하기 시작해야합니다!
3) 사용 가능한 대체 날짜 형식 중 하나를 사용하거나 64 비트 시스템으로 이동하여 64 비트 INT를 사용하십시오. 또는 데이터베이스의 경우 대체 타임 스탬프 형식을 사용합니다 (예 : MySQL 사용 DateTime의 경우)
4) 3 참조!
5) 4 참조 !!! ;)
BROS, 타임 스탬프를 표시하기 위해 PHP를 사용해야하는 경우 UNIX_TIMESTAMP 형식에서 변경하지 않고 최고의 PHP 솔루션입니다.
custom_date () 함수를 사용하십시오. 그 안에는 dateTime을 사용하십시오. 다음은 DateTime 솔루션입니다.
데이터베이스의 타임 스탬프로 서명되지 않은 Bigint (8)가있는 한. PHP 5.2.0 ++가있는 한
업그레이드하고 싶지 않기 때문에 백엔드 (MSSQL)에게 PHP 대신이 작업을 수행하도록 요청했습니다!
$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'];
효율적인 방법은 아니지만 작동합니다.