Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Sollte die Zeitzone von MySQL auf UTC eingestellt sein?

Es scheint, dass es keine Rolle spielt, welche Zeitzone sich auf dem Server befindet, solange Sie die richtige Zeit für die aktuelle Zeitzone eingestellt haben, die Zeitzone der von Ihnen gespeicherten datetime-Spalten kennen und sich der Probleme mit der Sommerzeit bewusst sind.

Wenn Sie andererseits die Zeitzonen der Server, mit denen Sie arbeiten, kontrollieren können, können Sie intern alles auf UTC einstellen und müssen sich nie um Zeitzonen und Sommerzeit kümmern.

Hier sind einige Notizen, die ich gesammelt habe, wie man mit Zeitzonen als eine Art Cheatsheet für mich und andere arbeitet, die beeinflussen könnten, welche Zeitzone die Person für ihren Server wählt und wie sie Datum und Uhrzeit speichert.

MySQL-Zeitzonen-Cheatsheet

Hinweise:

  1. Das Ändern der Zeitzone ändert nicht die gespeicherte Datumszeit oder den Zeitstempel , aber es wird eine andere datetime fromtimestamp-Spalte auswählen

  2. Warnung! UTC hat Schaltsekunden, diese sehen wie '2012-06-30 23:59:60' aus und können aufgrund der Verlangsamung der Erdrotation mit 6 Monaten Vorankündigung zufällig hinzugefügt werden

  3. GMT verwechselt Sekunden, weshalb UTC erfunden wurde.

  4. Warnung! unterschiedliche regionale Zeitzonen könnten aufgrund der Sommerzeit denselben datetime-Wert erzeugen

  5. Die Zeitstempelspalte unterstützt nur Daten von 1970-01-01 00:00:01 bis 2038-01-19 03:14:07 UTC, aufgrund von eine Einschränkung .

  6. Intern eine MySQL-Zeitstempelspalte wird als UTC gespeichert Aber wenn Sie ein Datum auswählen, konvertiert MySQL es automatisch in die Zeitzone der aktuellen Sitzung.

    Beim Speichern eines Datums in einem Zeitstempel geht MySQL davon aus, dass sich die Datei in der Zeitzone der aktuellen Sitzung befindet, und konvertiert sie zur Speicherung in UTC.

  7. MySQL kann Teildaten in datetime-Spalten speichern, diese sehen aus wie „2013-00-00 04:00:00“

  8. MySQL speichert „0000-00-00 00:00:00“, wenn Sie eine datetime-Spalte auf NULL setzen, es sei denn, Sie legen die Spalte ausdrücklich so fest, dass sie Null zulässt, wenn Sie sie erstellen.

  9. Lesen Sie dies

Um eine Zeitstempelspalte im UTC-Format auszuwählen

egal in welcher Zeitzone sich die aktuelle MySQL-Session befindet:

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

Sie können auch die Zeitzone des Servers oder der globalen oder aktuellen Sitzung auf UTC setzen und dann den Zeitstempel wie folgt auswählen:

SELECT `timestamp_field` FROM `table_name`

Um die aktuelle Datumszeit in UTC auszuwählen:

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

Beispielergebnis:2015-03-24 17:02:41

Zum Auswählen der aktuellen Datumszeit in der Sitzungszeitzone

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

Zum Auswählen der Zeitzone, die beim Starten des Servers festgelegt wurde

SELECT @@system_time_zone;

Gibt "MSK" oder "+04:00" für Moskauer Zeit zurück, es gibt (oder gab) einen MySQL-Bug, bei dem bei Einstellung auf einen numerischen Offset die Sommerzeit nicht angepasst wurde

Um die aktuelle Zeitzone abzurufen

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

Es wird 02:00:00 zurückgegeben, wenn Ihre Zeitzone +2:00 ist.

So erhalten Sie den aktuellen UNIX-Zeitstempel (in Sekunden):

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

So erhalten Sie die Zeitstempelspalte als UNIX-Zeitstempel

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

So erhalten Sie eine UTC-Datetime-Spalte als UNIX-Zeitstempel

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

Erhalten Sie eine aktuelle Zeitzone datetime aus einer positiven UNIX-Zeitstempel-Ganzzahl

SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`

Eine UTC-Datumszeit aus einem UNIX-Zeitstempel erhalten

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

Erhalten Sie eine aktuelle Zeitzone datetime aus einer negativen UNIX-Zeitstempel-Ganzzahl

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

Es gibt 3 Stellen, an denen die Zeitzone in MySQL eingestellt werden kann:

Hinweis:Eine Zeitzone kann in 2 Formaten eingestellt werden:

  1. ein Offset von UTC:'+00:00', '+10:00' oder '-6:00'
  2. als benannte Zeitzone:„Europe/Helsinki“, „US/Eastern“ oder „MET“

Benannte Zeitzonen können nur verwendet werden, wenn die Zeitzonen-Informationstabellen in der MySQL-Datenbank erstellt und ausgefüllt wurden.

in der Datei "my.cnf"

default_time_zone='+00:00'

oder

timezone='UTC'

@@global.time_zone-Variable

Um zu sehen, auf welchen Wert sie eingestellt sind

SELECT @@global.time_zone;

Um einen Wert dafür festzulegen, verwenden Sie entweder:

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

@@session.time_zone-Variable

SELECT @@session.time_zone;

Um es einzustellen, verwenden Sie entweder:

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

Sowohl "@@global.time_zone variable" als auch "@@session.time_zone variable" geben möglicherweise "SYSTEM" zurück, was bedeutet, dass sie die in "my.cnf" festgelegte Zeitzone verwenden.

Damit Zeitzonennamen funktionieren (sogar für Standard-Zeitzone), müssen Sie Ihre Zeitzonen-Informationstabellen einrichten, die ausgefüllt werden müssen: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html

Hinweis:Sie können dies nicht tun, da es NULL zurückgibt:

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

Mysql-Zeitzonentabellen einrichten

Für CONVERT_TZ Damit es funktioniert, müssen die Zeitzonentabellen gefüllt sein

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` ;

Wenn sie leer sind, füllen Sie sie mit diesem Befehl auf

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

wenn dieser Befehl den Fehler "data too long for column 'abbreviation' at row 1 “, dann könnte es daran liegen, dass am Ende der Zeitzonen-Abkürzung ein NULL-Zeichen angehängt wird

Die Lösung besteht darin, dies auszuführen

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

(Stellen Sie sicher, dass die dst-Regeln Ihres Servers auf dem neuesten Stand sind zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time- on-linux/ )

Siehe den vollständigen Verlauf der Umstellung auf die Sommerzeit (DST) für jede Zeitzone

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 wendet auch alle erforderlichen Sommerzeitänderungen basierend auf den Regeln in den obigen Tabellen und dem von Ihnen verwendeten Datum an.

Hinweis:
Laut den Dokumenten , ändert sich der Wert, den Sie für time_zone festlegen, nicht. Wenn Sie ihn beispielsweise auf „+01:00“ festlegen, wird die time_zone als Offset von UTC festgelegt, die nicht der Sommerzeit folgt, sodass sie für alle gleich bleibt ganzjährig.

Nur die genannten Zeitzonen ändert die Zeit während der Sommerzeit.

Abkürzungen wie CET wird immer eine Winterzeit und CEST sein Sommerzeit, während +01:00 immer UTC ist Zeit + 1 Stunde und beide ändern sich nicht mit der Sommerzeit.

Das system timezone ist die Zeitzone des Host-Rechners, auf dem mysql installiert ist (es sei denn, mysql kann sie nicht bestimmen)

Weitere Informationen zum Arbeiten mit der Sommerzeit finden Sie hier

Wann man UTC vom legendären Jon Skeet nicht verwenden sollte:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Zum Beispiel ein geplantes Ereignis in der Zukunft, das einen Zeitpunkt darstellt, keinen Zeitpunkt)

verwandte Fragen:

Quellen: