mysql - MySQL 是否应该将其时区设置为 UTC?

标签 mysql time utc

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

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

有什么优点和缺点?

最佳答案

只要您为当前时区设置了正确的时间,知道您存储的日期时间列的时区,并且知道夏令时的问题,服务器上的时区似乎并不重要。

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

以下是我收集的关于如何使用时区作为我自己和其他人的备忘单形式的一些笔记,这些笔记可能会影响该人将为他/她的服务器选择的时区以及他/她将如何存储日期和时间。

MySQL 时区备忘单

注意事项:

  • 更改时区 不会改变存储的日期时间或
    时间戳
    ,但它会从中选择一个不同的日期时间
    时间戳列
  • 警告! UTC 有闰秒,这些看起来像 '2012-06-30 23:59:60' 并且可以
    随机添加,提前 6 个月通知,由于速度减慢
    地球自转
  • GMT 混淆了秒,这就是发明 UTC 的原因。
  • 警告! 不同的区域时区可能会产生相同的日期时间值
    到夏令时
  • 由于 a limitation,时间戳列仅支持 1970-01-01 00:00:01 到 2038-01-19 03:14:07 UTC 的日期.
  • 内部一个 MySQL timestamp column存储为 UTC但是
    选择日期时,MySQL 会自动将其转换为
    当前 session 时区。

    在时间戳中存储日期时,MySQL 将假定日期
    处于当前 session 时区并将其转换为 UTC
    存储。
  • MySQL 可以在 datetime 列中存储部分日期,这些看起来像
    "2013-00-00 04:00:00"
  • 如果将日期时间列设置为,MySQL 将存储“0000-00-00 00:00:00”
    NULL,除非您特别设置该列以在您
    创建它。
  • Read this

  • 选择 UTC 格式的时间戳列

    无论当前 MySQL session 处于哪个时区:
    SELECT 
    CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime` 
    FROM `table_name`
    

    您还可以将服务器或全局或当前 session 时区设置为 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
    在 session 时区中选择当前日期时间
    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 种格式:
  • UTC 的偏移量:“+00:00”、“+10:00”或“-6:00”
  • 作为命名时区:“欧洲/赫尔辛基”、“美国/东部”或“大都会”

  • Named time zones can be used only if the time zone information tables in the mysql database have been created and populated.



    在文件“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
    

    如果此命令给您错误“data too long for column 'abbreviation' at row 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的偏移量,不遵循夏令时,所以它会保持不变全年。

    只有命名的 timezones将在夏令时更改时间。

    缩写如 CET永远是冬天,CEST将是夏令时,而 +01:00 将始终是 UTC time + 1 小时,两者都不会随 DST 改变。
    system时区将是安装 mysql 的主机的时区(除非 mysql 无法确定)

    您可以阅读有关使用 DST 的更多信息 here

    相关问题:
  • How do I set the time zone of MySQL?
  • MySql - SELECT TimeStamp Column in UTC format
  • How to get Unix timestamp in MySQL from UTC time?
  • Converting Server MySQL TimeStamp To UTC
  • https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
  • How do I get the current time zone of MySQL?
  • MySQL datetime fields and daylight savings time -- how do I reference the "extra" hour?
  • Converting negative values from 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
  • 关于mysql - MySQL 是否应该将其时区设置为 UTC?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19023978/

    相关文章:

    java - java 8中从日期字符串到utc long

    MYSQL 语法 - 带条件的 GROUP BY

    php - 设置脚本来访问单独的数据库

    当查询很大时MySQL无法正常工作

    php - MySQL 相当于 mysql_num_rows。哪个更好?

    php - SQLSTATE[HY000] : General error: 1298 Unknown or incorrect time zone: 'UTC' windows

    java - 在 Android 中设置可滚动的日期和时间选择器

    python - 如何在一定时间内运行代码?

    time - Paypal 日期格式 : what is "HH:MM:SS DD Mmm YY, YYYY PST"?

    mysql - JDBC/MySQL : Save timestamp always using UTC