如果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时区备忘单
笔记:
- 更改时区不会更改存储的date时间或时间戳 ,但会从时间戳列中select不同的date时间
- UTC不使用夏令时,格林尼治标准时间(格林威治标准时间),格林尼治标准时间(GMT)也没有(格林尼治标准时间也混淆秒的定义,这就是为什么UTC发明)。
- 警告! UTC有闰秒,这些看起来像“2012-06-30 23:59:60”,可以随意添加,提前6个月通知,由于地球自转减慢
- 警告! 由于夏令时,不同的地区时区可能会产生相同的date时间值
- 时间戳列仅支持date1970-01-01 00:00:01至2038-01-19 03:14:07 UTC
-
在内部, MySQL时间戳列存储为UTC,但是在selectdate时,MySQL会自动将其转换为当前会话时区。
在时间戳中存储date时,MySQL将假定date在当前会话时区,并将其转换为UTC进行存储。
- MySQL可以在datetime列中存储部分date,这些列表看起来像“2013-00-00 04:00:00”
- 如果将date时间列设置为NULL,则MySQL存储“0000-00-00 00:00:00”,除非您在创build列时专门设置了允许为空的列。
- 读这个
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中设置时区:
注意:时区可以设置为两种格式:
- 与UTC的偏移量:“+00:00”,“+10:00”或“-6:00”
- 作为指定时区:“欧洲/赫尔辛基”,“美国/东部”或“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的信息
相关问题:
- 我如何设置MySQL的时区?
- MySql – UTC格式的SELECT TimeStamp列
- 如何从UTC时间在MySQL中获得Unix时间戳?
- 将服务器MySQL TimeStamp转换为UTC
- https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- 我如何获得MySQL的当前时区?
- MySQLdate时间字段和夏令时 – 我如何引用“额外”小时?
- 从FROM_UNIXTIME转换负值
资料来源:
- https://bugs.mysql.com/bug.php?id=68861
- http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
- http://dev.mysql.com/doc/refman/5.1/en/datetime.html
- http://en.wikipedia.org/wiki/Coordinated_Universal_Time
- http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
- https://web.ivy.net/~carton/rant/MySQL-timezones.txt
PHP和MySQL有自己的默认时区configuration。 您应该同步数据库和Web应用程序之间的时间,否则可能会遇到一些问题。
阅读本教程: 如何同步您的PHP和MySQL时区
优点和缺点是非常相同的,这取决于你是否想要这个。
要小心,如果MySQL时区与您的系统时间(例如PHP)不同,比较时间或打印到用户将涉及一些修补程序。