sql >> Databáze >  >> RDS >> Mysql

Mělo by mít MySQL nastavené časové pásmo na UTC?

Zdá se, že nezáleží na tom, jaké časové pásmo je na serveru, pokud máte správně nastavený čas pro aktuální časové pásmo, znáte časové pásmo ve sloupcích datetime, které ukládáte, a jste si vědomi problémů s letním časem.

Na druhou stranu, pokud máte kontrolu nad časovými pásmy serverů, se kterými pracujete, můžete mít vše interně nastaveno na UTC a nemusíte se nikdy starat o časová pásma a letní čas.

Zde je několik poznámek, které jsem shromáždil o tom, jak pracovat s časovými pásmy jako formou cheatsheetu pro mě a ostatní, které mohou ovlivnit, jaké časové pásmo si uživatel vybere pro svůj server a jak bude ukládat datum a čas.

Chatová tabulka časového pásma MySQL

Poznámky:

  1. Změna časového pásma nezmění uložené datum a čas nebo časové razítko , ale vybere jiné datum a čas ze sloupců časového razítka

  2. Upozornění! UTC má přestupné sekundy, ty vypadají jako '2012-06-30 23:59:60' a mohou být přidány náhodně, s upozorněním 6 měsíců předem, kvůli zpomalení rotace Země

  3. GMT mate sekundy, a proto bylo vynalezeno UTC.

  4. Upozornění! různá regionální časová pásma mohou mít stejnou hodnotu data a času kvůli letnímu času

  5. Sloupec časového razítka podporuje pouze data 1970-01-01 00:00:01 až 2038-01-19 03:14:07 UTC, kvůli omezení .

  6. Interně sloupec časového razítka MySQL je uloženo jako UTC ale když vyberete datum, MySQL jej automaticky převede na časové pásmo aktuální relace.

    Při ukládání data do časového razítka bude MySQL předpokládat, že datum je v aktuálním časovém pásmu relace a převede ho na UTC pro uložení.

  7. MySQL může ukládat částečná data do sloupců data a času, ty vypadají jako "2013-00-00 04:00:00"

  8. MySQL ukládá "0000-00-00 00:00:00", pokud nastavíte sloupec datetime jako NULL, pokud sloupec výslovně nenastavíte tak, aby při jeho vytvoření umožňoval hodnotu null.

  9. Přečíst

Výběr sloupce časového razítka ve formátu UTC

bez ohledu na to, v jakém časovém pásmu se aktuální relace MySQL nachází:

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

Můžete také nastavit časové pásmo serveru nebo globální nebo aktuální časové pásmo relace na UTC a poté vybrat časové razítko takto:

SELECT `timestamp_field` FROM `table_name`

Výběr aktuálního data a času v UTC:

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

Příklad výsledku:2015-03-24 17:02:41

Výběr aktuálního data a času v časovém pásmu relace

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

Výběr časového pásma, které bylo nastaveno při spuštění serveru

SELECT @@system_time_zone;

Vrací „MSK“ nebo „+04:00“ pro moskevský čas, například existuje (nebo byla) chyba MySQL, kde nastavení na číselný posun neupraví letní čas

Získání aktuálního časového pásma

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

Pokud je vaše časové pásmo +2:00, vrátí se 02:00:00.

Chcete-li získat aktuální časové razítko UNIX (v sekundách):

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

Chcete-li získat sloupec časového razítka jako časové razítko UNIX

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

Chcete-li získat sloupec data a času UTC jako časové razítko UNIX

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

Získejte aktuální datum a čas časového pásma z kladného celého čísla časového razítka UNIX

SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`

Získejte datum a čas UTC z časového razítka UNIX

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

Získejte aktuální datum a čas časového pásma ze záporného celého čísla časového razítka UNIX

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

Existují 3 místa, kde lze v MySQL nastavit časové pásmo:

Poznámka:Časové pásmo lze nastavit ve 2 formátech:

  1. posun od UTC:'+00:00', '+10:00' nebo '-6:00'
  2. jako pojmenované časové pásmo:„Europe/Helsinki“, „US/Eastern“ nebo „MET“

Pojmenovaná časová pásma lze použít pouze v případě, že byly vytvořeny a naplněny informační tabulky časových pásem v databázi mysql.

v souboru "my.cnf"

default_time_zone='+00:00'

nebo

timezone='UTC'

@@global.time_zone variable

Chcete-li zjistit, na jakou hodnotu jsou nastaveny

SELECT @@global.time_zone;

Chcete-li pro něj nastavit hodnotu, použijte jednu z následujících možností:

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

proměnná @session.time_zone

SELECT @@session.time_zone;

Chcete-li jej nastavit, použijte jednu z následujících možností:

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

jak "@@global.time_zone variable" tak "@@session.time_zone variable" mohou vrátit "SYSTEM", což znamená, že používají časové pásmo nastavené v "my.cnf".

Aby názvy časových pásem fungovaly (i pro výchozí časové pásmo), musíte nastavit, aby tabulky s informacemi o časových pásmech byly vyplněny: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html

Poznámka:Toto nemůžete udělat, protože to vrátí NULL:

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

Nastavení tabulek časových pásem mysql

Pro CONVERT_TZ Chcete-li pracovat, potřebujete, aby byly vyplněny tabulky časových pásem

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

Pokud jsou prázdné, vyplňte je spuštěním tohoto příkazu

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

pokud vám tento příkaz zobrazí chybu "data jsou příliš dlouhá pro sloupec 'zkratka' na řádku 1 ", pak to může být způsobeno znakem NULL připojeným na konec zkratky časového pásma

opravou je spuštění tohoto

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

(ujistěte se, že jsou pravidla dst vašich serverů aktuální zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time- on-linux/ )

Zobrazit úplnou historii přechodu DST (letního času) pro každé časové pásmo

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 také použije všechny nezbytné změny DST na základě pravidel ve výše uvedených tabulkách a data, které používáte.

Poznámka:
Podle dokumentů , hodnota, kterou jste nastavili pro time_zone, se nezmění, pokud ji nastavíte například jako "+01:00", pak time_zone bude nastaveno jako offset od UTC, které nesleduje DST, takže zůstane stejné. celoročně.

Pouze vyjmenovaná časová pásma změní čas během letního času.

Zkratky jako CET bude vždy zimní čas a CEST bude letní čas, zatímco +01:00 bude vždy UTC čas + 1 hodina a obě se s DST nezmění.

system timezone bude časové pásmo hostitelského počítače, kde je nainstalován mysql (pokud ho mysql nedokáže určit)

Další informace o práci s DST si můžete přečíst zde

Kdy nepoužívat UTC od legendárního Jona Skeeta:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Například plánovaná událost v budoucnosti, která představuje čas, nikoli okamžik v čase)

související otázky:

Zdroje:



  1. MySQL InnoDB Cluster 8.0 – kompletní průvodce nasazením:část první

  2. Proč byla požadována neplatná konverze KÓD CHYBY:17132?

  3. Jak zkontrolovat, zda soubor používá obrázek PL/SQL?

  4. Jak spojit cx_oracle s Pyinstallerem