programing

PHP & mySQL: 2038년 버그: 뭐죠?어떻게 해결할까요?

projobs 2022. 9. 22. 22:11
반응형

PHP & mySQL: 2038년 버그: 뭐죠?어떻게 해결할까요?

TIMESTAMP를 사용하여 날짜+시간을 저장하려고 했는데 2038년이라는 제한이 있다고 읽었습니다.질문을 일괄적으로 하는 것이 아니라, 초보자도 이해하기 쉽도록 작은 부분으로 나누는 것을 선호했습니다.그래서 질문하겠습니다.

  1. 2038년 문제는 정확히 무엇입니까?
  2. 왜 그런 일이 일어나는지, 그리고 그 일이 일어나면 어떻게 됩니까?
  3. 어떻게 해결할까요?
  4. 유사한 문제가 발생하지 않는 다른 방법이 있습니까?
  5. 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 유형:

DATETIMEtype은 날짜와 시간 정보를 모두 포함하는 값이 필요할 때 사용합니다.지원되는 범위는 다음과 같습니다.'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년 이전에 여러 번 재작성되었을 가능성이 매우 높습니다.^^앞으로 날짜에 대처할 필요가 없다면 현재 버전의 어플리케이션에서 이 문제를 해결할 필요가 없습니다.

Google에서 빠르게 검색하면 다음과 같은 효과를 얻을 수 있는 것은 다음과 같습니다.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비트 서명된 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

반응형