PHP & mySQL: 2038년 버그: 뭐죠?어떻게 해결할까요?
TIMESTAMP를 사용하여 날짜+시간을 저장하려고 했는데 2038년이라는 제한이 있다고 읽었습니다.질문을 일괄적으로 하는 것이 아니라, 초보자도 이해하기 쉽도록 작은 부분으로 나누는 것을 선호했습니다.그래서 질문하겠습니다.
- 2038년 문제는 정확히 무엇입니까?
- 왜 그런 일이 일어나는지, 그리고 그 일이 일어나면 어떻게 됩니까?
- 어떻게 해결할까요?
- 유사한 문제가 발생하지 않는 다른 방법이 있습니까?
- TIMESTAMP를 사용하는 기존 애플리케이션에 대해 실제로 문제가 발생했을 때 이를 방지하기 위해 무엇을 할 수 있을까요?
잘 부탁드립니다.
커뮤니티 위키로 표시했으므로, 자유롭게 편집해 주세요.
2038년 문제는 정확히 무엇입니까?
「2038년의 문제(Y2K의 문제에 비유해 Unix Millennium Bug, Y2K38이라고도 불립니다)로 인해, 일부의 컴퓨터 소프트웨어가 2038년 이전 또는 그 이후에 장해가 발생할 가능성이 있습니다.이 문제는 시스템 시간을 부호 있는 32비트 정수로 저장하고 1970년 1월 1일 00:00:00 UTC 이후 초수로 해석하는 모든 소프트웨어와 시스템에 영향을 미칩니다."
왜 그런 일이 일어나는지, 그리고 그 일이 일어나면 어떻게 됩니까?
2038년 1월 19일 화요일 03:14:07 UTC를 초과하면 '감겨서 음수'로 내부에 저장됩니다.이러한 시간들은 2038년이 아닌 1901년 12월 13일의 시간으로 해석됩니다.이는 UNIX Epoch(1970년 1월 1일 00:00 GMT) 이후 초수가 32비트 부호 있는 정수의 컴퓨터 최대값을 초과하기 때문입니다.
어떻게 해결할까요?
- 긴 데이터 유형 사용(64비트면 충분)
- MySQL(또는 MariaDB)의 경우 시간 정보가 필요 없는 경우
DATE
컬럼 타입더 높은 정확도가 필요한 경우DATETIME
보다는TIMESTAMP
다음 점에 주의해 주십시오.DATETIME
컬럼에는 타임존에 대한 정보가 저장되지 않기 때문에 응용 프로그램은 어떤 타임존이 사용되었는지 알아야 합니다. - Wikipedia에 기재되어 있는 기타 가능한 해결책
- Mysql을 8.0.28 이상으로 업그레이드합니다.
유사한 문제가 발생하지 않는 다른 방법이 있습니까?
가능한 한 큰 타입을 사용하여 데이터베이스에 날짜를 저장해 보십시오.64비트면 충분합니다.GNU C 및 POSIX/SuS에서는 긴 타입입니다.sprintf('%u'...)
PHP 또는 BCmath 확장자로 지정합니다.
아직 2038년이 되지 않았는데 잠재적으로 문제가 될 수 있는 사용 사례는 무엇입니까?
따라서 MySQL DATETIME의 범위는 1000~9999이지만 TIMESTAMP의 범위는 1970~2038뿐입니다.시스템에 생년월일, 미래 미래 날짜(예: 30년 주택담보대출) 등이 저장되어 있다면 이미 이 버그가 발생할 것입니다.다시 말하지만 문제가 발생할 경우 TIMESTAMP를 사용하지 마십시오.
TIMESTAMP를 사용하는 기존 애플리케이션에 대해 실제로 문제가 발생했을 때 이를 방지하기 위해 무엇을 할 수 있을까요?
웹이 아직 레거시 플랫폼이 아니기 때문에 예측하기 어렵지만, 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 타임스탬프를 사용하여 날짜를 저장하는 경우 실제로는 1970-01-01 이후의 초수를 카운트하는 32비트 정수를 사용합니다.「 Unix Time 」를 참조해 주세요.
이 32비트 번호는 2038년에 오버플로우 됩니다.그게 2038년 문제입니다.
이 문제를 해결하려면 날짜를 저장하기 위해 32비트 UNIX 타임스탬프를 사용해서는 안 됩니다. 즉, MySQL을 사용할 때,TIMESTAMP
,그렇지만DATETIME
(10.3.1 참조). DATETIME, DATE 및 TIMESTAMP 유형:
그
DATETIME
type은 날짜와 시간 정보를 모두 포함하는 값이 필요할 때 사용합니다.지원되는 범위는 다음과 같습니다.'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일 화요일 03:14:07 UTC입니다.이 순간 이후의 시간은 "감겨" 음수로 내부에 저장됩니다. 이러한 시스템은 2038년이 아닌 1901년의 날짜로 해석합니다.
- 기존 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' 참조!!;)
형제자매 여러분, 타임스탬프를 표시하기 위해 PHP를 사용해야 한다면 UNIX_TIMESTamp 형식에서 변경하지 않는 것이 가장 좋은 PHP 솔루션입니다.
custom_date() 함수를 사용합니다.그 안에서 Date Time을 사용합니다.여기 Date Time 솔루션이 있습니다.
데이터베이스에 타임스탬프로 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'];
효율적인 방법은 아닐지 몰라도 효과가 있어요
언급URL : https://stackoverflow.com/questions/2012589/php-mysql-year-2038-bug-what-is-it-how-to-solve-it
'programing' 카테고리의 다른 글
Visual Studio Code에서 생성된 vue-cli 3 앱 디버깅 (0) | 2022.09.22 |
---|---|
PHP5에 오류가 있습니다.동적 라이브러리를 로드할 수 없습니다. (0) | 2022.09.22 |
Django 모델 폼 객체의 자동 생성 날짜 (0) | 2022.09.22 |
iframe에서 'X-Frame-Options'를 설정하는 방법 (0) | 2022.09.22 |
스태틱 클래스의 초기화는 언제 이루어집니까? (0) | 2022.09.22 |