MySQL의 시간대를 UTC로 설정해야합니까?


149

/server/191331/should-servers-have-their-timezone-set-to-gmt-utc의 후속 질문

MySQL 시간대를 UTC로 설정해야합니까 아니면 서버 또는 PHP가 설정된 시간대와 동일하게 설정해야합니까? (UTC가 아닌 경우)

장단점은 무엇입니까?



UTC는 시간대가 아닙니다. UTC는 표준이고 GMT는 시간대입니다. zachholman.com/talk/utc-is-enough-for-everyone-right
agoldev

답변:


533

현재 시간대에 맞게 시간을 설정하고 저장 한 날짜 / 시간 열의 시간대를 알고 일광 절약 시간의 문제를 알고있는 한 서버의 시간대는 중요하지 않습니다.

반면에 작업하는 서버의 시간대를 제어 할 수 있으면 모든 것을 내부적으로 UTC로 설정하고 시간대와 DST에 대해 걱정할 필요가 없습니다.

다음은 시간대를 자신과 다른 사람을위한 치트 시트의 형태로 사용하는 방법에 대해 수집 한 메모입니다.이 시간대는 사람이 서버에 대해 어떤 시간대를 선택할지, 날짜와 시간을 어떻게 저장할지에 영향을 줄 수 있습니다.

MySQL 시간대 치트 시트

노트:

  1. 시간대 를 변경해도 저장된 datetime 또는 timestamp는 변경되지 않지만 timestamp 열과 다른 날짜 / 시간을 선택합니다
  2. 경고! UTC는 윤초가 있으며 '2012-06-30 23:59:60'과 같으며 지구 회전 속도가 느려져 6 개월 전에 사전 통지없이 임의로 추가 할 수 있습니다.
  3. GMT는 초를 혼동하므로 UTC가 발명되었습니다.

  4. 경고! 다른 지역 시간대는 일광 절약 시간 제로 인해 동일한 날짜 시간 값을 생성 할 수 있습니다

  5. 타임 스탬프 열 은 제한 으로 인해 1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 UTC 만 지원합니다 .
  6. 내부적으로 MySQL 타임 스탬프 열UTC 로 저장 되지만 날짜를 선택하면 MySQL이 자동으로 현재 세션 시간대로 변환합니다.

    타임 스탬프에 날짜를 저장하면 MySQL은 날짜가 현재 세션 시간대에 있다고 가정하고 저장을 위해 UTC로 변환합니다.

  7. MySQL은 날짜 / 시간 열에 부분 날짜를 저장할 수 있으며 "2013-00-00 04:00:00"과 같습니다.
  8. datetime 열을 NULL로 설정하면 열을 만들 때 null을 허용하도록 특별히 설정하지 않는 한 MySQL은 "0000-00-00 00:00:00"을 저장합니다.
  9. 이것을 읽으십시오

UTC 형식으로 타임 스탬프 열을 선택하려면

현재 MySQL 세션의 시간대에 관계없이

SELECT 
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime` 
FROM `table_name`

서버 또는 글로벌 또는 현재 세션 시간대를 UTC로 설정 한 다음 타임 스탬프를 다음과 같이 선택할 수도 있습니다.

SELECT `timestamp_field` FROM `table_name`

UTC로 현재 날짜 시간을 선택하려면

SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');

결과 예 : 2015-03-24 17:02:41

세션 시간대에서 현재 날짜 / 시간을 선택하려면

SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();

서버가 시작될 때 설정된 시간대를 선택하려면

SELECT @@system_time_zone;

모스크바 시간에 대해 "MSK"또는 "+04 : 00"을 반환합니다. 예를 들어, 숫자 오프셋으로 설정하면 일광 절약 시간이 조정되지 않는 MySQL 버그가 있거나있었습니다

현재 시간대를 얻으려면

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

시간대가 +2 : 00이면 02:00:00을 반환합니다.

현재 UNIX 타임 스탬프를 가져 오려면 (초) :

SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();

타임 스탬프 열을 UNIX 타임 스탬프로 가져 오려면

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

UTC 날짜 / 시간 열을 UNIX 타임 스탬프로 가져 오려면

SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`

양의 UNIX 타임 스탬프 정수에서 현재 시간대 날짜 시간 가져 오기

SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`

UNIX 타임 스탬프에서 UTC 날짜 시간 가져 오기

SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00') 
FROM `table_name`

음의 UNIX 타임 스탬프 정수에서 현재 시간대 날짜 시간 가져 오기

SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND) 

MySQL에서 시간대를 설정할 수있는 장소는 3 곳입니다.

참고 : 시간대는 2 가지 형식으로 설정할 수 있습니다.

  1. UTC에서 오프셋 : '+00 : 00', '+10 : 00'또는 '-6 : 00'
  2. 명명 된 시간대 : '유럽 / 헬싱키', '미국 / 동부'또는 'MET'

명명 된 표준 시간대는 mysql 데이터베이스의 표준 시간대 정보 테이블이 생성되고 채워진 경우에만 사용할 수 있습니다.

"my.cnf"파일에서

default_time_zone='+00:00'

또는

timezone='UTC'

@@ global.time_zone 변수

그들이 어떤 값으로 설정되어 있는지 확인하려면

SELECT @@global.time_zone;

값을 설정하려면 다음 중 하나를 사용하십시오.

SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';

@@ session.time_zone 변수

SELECT @@session.time_zone;

설정하려면 다음 중 하나를 사용하십시오.

SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";

"@@ global.time_zone 변수"및 "@@ session.time_zone 변수"는 "SYSTEM"을 반환 할 수 있습니다. 즉 "my.cnf"에 설정된 시간대를 사용합니다.

시간대 이름이 작동하려면 (기본 시간대의 경우에도) 시간대 정보 테이블을 채워야합니다 ( http://dev.mysql.com/doc/refman/5.1/en/time-zone-support). html

참고 : NULL을 반환 하므로이 작업을 수행 할 수 없습니다.

SELECT 
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime` 
FROM `table_name`

MySQL 시간대 테이블 설정

들어 CONVERT_TZ작업에, 당신은 시간대 테이블이 채워해야

SELECT * FROM mysql.`time_zone` ;
SELECT * FROM mysql.`time_zone_leap_second` ;
SELECT * FROM mysql.`time_zone_name` ;
SELECT * FROM mysql.`time_zone_transition` ;
SELECT * FROM mysql.`time_zone_transition_type` ;

비어있는 경우이 명령을 실행하여 채우십시오.

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

이 명령 에서 " 행 1의 열 '약어'에 대한 데이터가 너무 깁니다 "오류 가 발생하면 시간대 약어의 끝에 NULL 문자가 추가되어 발생할 수 있습니다.

이 문제를 해결하는 수정

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
(if the above gives error "data too long for column 'abbreviation' at row 1")
mysql_tzinfo_to_sql /usr/share/zoneinfo > /tmp/zut.sql

echo "SET SESSION SQL_MODE = '';" > /tmp/mysql_tzinfo_to.sql
cat /tmp/zut.sql >> /tmp/mysql_tzinfo_to.sql

mysql --defaults-file=/etc/mysql/my.cnf --user=verifiedscratch -p mysql < /tmp/mysql_tzinfo_to.sql

(서버의 dst 규칙이 최신 상태인지 확인하십시오 zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time-on-linux/ )

모든 시간대에 대한 전체 DST (일광 절약 시간) 전환 기록보기

SELECT 
tzn.Name AS tz_name,
tztt.Abbreviation AS tz_abbr,
tztt.Is_DST AS is_dst,
tztt.`Offset` AS `offset`,
DATE_ADD('1970-01-01 00:00:00',INTERVAL tzt.Transition_time SECOND)  AS transition_date
FROM mysql.`time_zone_transition` tzt
INNER JOIN mysql.`time_zone_transition_type` tztt USING(Time_zone_id, Transition_type_id)
INNER JOIN mysql.`time_zone_name` tzn USING(Time_zone_id)
-- WHERE tzn.Name LIKE 'Europe/Moscow' -- Moscow has weird DST changes
ORDER BY tzt.Transition_time ASC

CONVERT_TZ 또한 위 표의 규칙과 사용 날짜에 따라 필요한 DST 변경 사항이 적용됩니다.

참고 : docs
에 따르면 time_zone에 설정 한 값은 변경되지 않습니다. 예를 들어 "+01 : 00"으로 설정하면 time_zone은 UTC에서 오프셋으로 설정되어 DST를 따르지 않습니다. 일년 내내 동일하게 유지됩니다.

명명 된 시간대 만 일광 절약 시간제 시간 동안 변경됩니다.

같은 약어 CET는 항상 겨울철이며 CEST여름철이며 +01 : 00은 항상 UTC시간 + 1 시간이며 둘 다 DST로 변경되지 않습니다.

system(MySQL은 그것을 결정하지 않는 한) 시간대는 MySQL의가 설치되어있는 호스트 시스템의 시간대 될 것입니다

DST 작업에 대한 자세한 내용은 여기를 참조하십시오.

관련 질문 :

출처 :


따라서 열 유형을 타임 스탬프로 설정하면 그리고 내 시간대는 +12 : 00이며 utc 기반 날짜 / 시간을 사용하여 열을 업데이트하고 싶습니다. 업데이트 명령문에 시간대를 포함시킬 방법이 있습니까? 아니면 convert_tz를 사용해야합니다. 예 : 업데이트 table설정 modified= '2016년 7월 7일 8시 10분 00 : 00'
bumperbox

2
@bumperbox mysql은 항상 타임 스탬프 열을 제공하는 날짜가 mysql 서버와 동일한 시간대에 있다고 가정하므로 업데이트를 위해 날짜를 +12 : 00 시간대에서 mysql 서버 시간대로 변환해야합니다. 이것이 MySQL 서버에서 UTC를 사용하고 저장하기 전에 날짜를 UTC로 변환하는 이유입니다.
Timo Huovinen

5
몇 년 동안 SO를 사용하면서 얻은 가장 유익한 정보 중 하나입니다. 감사합니다.
Mitya

경고!!! DST 시간대에서 현지 시간을 사용하거나 변환하는 것은 일광 절약 시간이 끝날 때마다 한 시간 씩 1 시간 씩 틀립니다. 이는 파라미터 중 하나가`@@ session.time_zone 인 UNIX_TIMESTAMP(NOW());모든 용도에 영향을 미칩니다 CONVERT_TZ(). UTC 날짜 시간을 UNIX 타임 스탬프로 안정적으로 변환하려면 기본적으로 세션 time_zone을 먼저 설정해야합니다.
Doin

1
@Flimm 완전히 옳았습니다. 몇 시간 전에 고치는 것을 잊었습니다.
Timo Huovinen 2016 년

3

이것은 실제 예입니다.

jdbc:mysql://localhost:3306/database?useUnicode=yes&characterEncoding=UTF-8&serverTimezone=Europe/Moscow

2

PHP와 MySQL에는 자체 기본 시간대 구성이 있습니다. 데이터베이스와 웹 애플리케이션간에 시간을 동기화해야합니다. 그렇지 않으면 일부 문제가 발생할 수 있습니다.

이 튜토리얼을 읽으십시오 : PHP와 MySQL 시간대를 동기화하는 방법


그것은 기본적으로 두 줄의 코드입니다 : date_default_timezone_set("America/Los_Angeles");mysql_query("SET time_zone='" . date('P', time()) . "'");매우 우아하게 일했다!
누 메논

3
@Noumenon 조심해! 나는 오늘 아침 내 머리를 긁어 왔는데, 그것이 내가하고있는 일이기 때문에, 내 시간 중 일부는 지금 한 시간 늦습니다. DST가 관련되어 있으면 명명 된 시간대를 사용하는 것이 더 정확하다고 생각합니다. America / New_York를 사용하는 경우 MySQL은 DST에 대해 알고 날짜를 적절히 저장합니다. 여기에서와 같이 -04 : 00으로 설정하면 DST 계산을 고려하지 않습니다.
nathanb

1
mysql이 DST에 대해 올바르게 알고 있는지 확인하고 DST 규칙이 정기적으로 업데이트되며 관련 mysql 테이블도 업데이트해야합니다 (위의 답변 맨 아래 참조)
Timo Huovinen

1

장단점은 거의 동일하며, 원하는지 여부에 따라 다릅니다.

MySQL 시간대가 시스템 시간 (예 : PHP)과 다르면 시간을 비교하거나 사용자와 인쇄하는 데 약간의 시간이 소요됩니다.

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