如果MySQL的时区设置为UTC?

跟进https://serverfault.com/questions/191331/should-servers-have-their-timezone-set-to-gmt-utc的问题

MySQL的时区应该设置为UTC,还是应该设置为与服务器相同的时区,或者设置了PHP? (如果不是UTC)

优缺点都有什么?

只要您有适合当前时区的时间,知道您存储的date时间列的时区,并且知道夏令时问题,似乎服务器上的时区并不重要。

另一方面,如果您可以控制与您一起工作的服务器的时区,那么您可以将所有内容设置为UTC,而不必担心时区和DST。

以下是我收集的关于如何使用时区作为自己和其他人的备忘录forms的一些说明,这些备忘录可能会影响用户为他/她的服务器select什么时区以及他/她如何存储date和时间。

MySQL时区备忘单

笔记:

  1. 更改时区不会更改存储的date时间或时间戳 ,但会从时间戳列中select不同的date时间
  2. UTC不使用夏令时,格林尼治标准时间(格林威治标准时间),格林尼治标准时间(GMT)也没有(格林尼治标准时间也混淆秒的定义,这就是为什么UTC发明)。
  3. 警告! UTC有闰秒,这些看起来像“2012-06-30 23:59:60”,可以随意添加,提前6个月通知,由于地球自转减慢
  4. 警告! 由于夏令时,不同的地区时区可能会产生相同的date时间值
  5. 时间戳列仅支持date1970-01-01 00:00:01至2038-01-19 03:14:07 UTC
  6. 在内部, MySQL时间戳列存储为UTC,但是在selectdate时,MySQL会自动将其转换为当前会话时区。

    在时间戳中存储date时,MySQL将假定date在当前会话时区,并将其转换为UTC进行存储。

  7. MySQL可以在datetime列中存储部分date,这些列表看起来像“2013-00-00 04:00:00”
  8. 如果将date时间列设置为NULL,则MySQL存储“0000-00-00 00:00:00”,除非您在创build列时专门设置了允许为空的列。
  9. 读这个

selectUTC格式的时间戳列

不pipe当前的MySQL会话在什么时区:

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

您还可以将服务器或全球或当前会话时区设置为UTC,然后select时间戳,如下所示:

 SELECT `timestamp_field` FROM `table_name` 

要selectUTC中的当前date时间:

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

示例结果: 2015-03-24 17:02:41

在会话时区中select当前date时间

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

select服务器启动时设置的时区

 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` 

获取UTCdate时间列作为UNIX时间戳

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

从肯定的UNIX时间戳整数中获取当前的时区date时间

 SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name` 

从UNIX时间戳获取UTCdate时间

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

从负的UNIX时间戳整数中获取当前的时区date时间

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

有3个地方可能在MySQL中设置时区:

注意:时区可以设置为两种格式:

  1. 与UTC的偏移量:“+00:00”,“+10:00”或“-6:00”
  2. 作为指定时区:“欧洲/赫尔辛基”,“美国/东部”或“MET”

命名时区只有在创build和填充mysql数据库中的时区信息表时才能使用。

在文件“my.cnf”

 default_time_zone='+00:00' 

要么

 timezone='UTC' 

@@ global.time_zonevariables

看看他们设置了什么价值

 SELECT @@global.time_zone; 

要为其设置一个值,请使用以下任一值:

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

@@ session.time_zonevariables

 SELECT @@session.time_zone; 

要设置它使用任一:

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

“@@ global.time_zonevariables”和“@@ session.time_zonevariables”可能会返回“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 

(确保你的服务器的规则是最新的zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time-on-linux/

查看每个时区的完整DST(夏时制)转换历史logging

 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还会根据上表中的规则和您使用的date应用任何必要的DST更改。

注意:
根据文档 ,为time_zone设置的值不会改变,例如,如果将其设置为“+01:00”,那么time_zone将设置为UTC的偏移量,而不跟随DST,所以它会全年保持不变。

只有指定的时区才会在夏令时期间改变时间。

CET这样的缩写总是一个冬天的时间, CEST将会是夏天,而+01:00会一直是UTC时间+ 1小时,两者都不会随着DST而改变。

system时区将是安装mysql的主机的时区(除非mysql无法确定)

您可以在这里阅读更多关于使用DST的信息

相关问题:

资料来源:

PHP和MySQL有自己的默认时区configuration。 您应该同步数据库和Web应用程序之间的时间,否则可能会遇到一些问题。

阅读本教程: 如何同步您的PHP和MySQL时区

优点和缺点是非常相同的,这取决于你是否想要这个。

要小心,如果MySQL时区与您的系统时间(例如PHP)不同,比较时间或打印到用户将涉及一些修补程序。