sql >> Database >  >> RDS >> Mysql

Moet de tijdzone van MySQL worden ingesteld op UTC?

Het lijkt erop dat het niet uitmaakt welke tijdzone zich op de server bevindt, zolang je de tijd goed hebt ingesteld voor de huidige tijdzone, de tijdzone kent van de datetime-kolommen die je opslaat en je bewust bent van de problemen met zomertijd.

Aan de andere kant, als u controle heeft over de tijdzones van de servers waarmee u werkt, kunt u alles intern op UTC instellen en hoeft u zich geen zorgen te maken over tijdzones en DST.

Hier zijn enkele opmerkingen die ik heb verzameld over het werken met tijdzones als een soort cheatsheet voor mezelf en anderen, die van invloed kunnen zijn op de tijdzone die de persoon kiest voor zijn/haar server en hoe hij/zij de datum en tijd opslaat.

MySQL-tijdzone-cheatsheet

Opmerkingen:

  1. Het wijzigen van de tijdzone zal de opgeslagen datum/tijdstempel niet wijzigen , maar het zal een andere datum/tijd selecteren uit de kolommen met tijdstempel

  2. Waarschuwing! UTC heeft schrikkelseconden, deze zien eruit als '2012-06-30 23:59:60' en kunnen willekeurig worden toegevoegd, met een opzegtermijn van 6 maanden, vanwege de vertraging van de rotatie van de aarde

  3. GMT verwart seconden, daarom is UTC uitgevonden.

  4. Waarschuwing! verschillende regionale tijdzones kunnen vanwege de zomertijd dezelfde datum/tijd-waarde opleveren

  5. De tijdstempelkolom ondersteunt alleen datums 1970-01-01 00:00:01 tot 2038-01-19 03:14:07 UTC, vanwege een beperking .

  6. Intern een MySQL-tijdstempelkolom wordt opgeslagen als UTC maar bij het selecteren van een datum zal MySQL deze automatisch converteren naar de tijdzone van de huidige sessie.

    Bij het opslaan van een datum in een tijdstempel, gaat MySQL ervan uit dat de datum zich in de tijdzone van de huidige sessie bevindt en converteert deze naar UTC voor opslag.

  7. MySQL kan gedeeltelijke datums opslaan in datetime-kolommen, deze zien eruit als "2013-00-00 04:00:00"

  8. MySQL slaat "0000-00-00 00:00:00" op als u een datetime-kolom instelt als NULL, tenzij u de kolom specifiek instelt om null toe te staan ​​wanneer u deze aanmaakt.

  9. Lees dit

Een tijdstempelkolom in UTC-indeling selecteren

ongeacht in welke tijdzone de huidige MySQL-sessie zich bevindt:

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

U kunt ook de tijdzone van de server of de globale of huidige sessie instellen op UTC en vervolgens het tijdstempel als volgt selecteren:

SELECT `timestamp_field` FROM `table_name`

Om de huidige datum/tijd in UTC te selecteren:

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

Voorbeeld resultaat:2015-03-24 17:02:41

Om de huidige datetime in de sessietijdzone te selecteren

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

Om de tijdzone te selecteren die was ingesteld toen de server werd gelanceerd

SELECT @@system_time_zone;

Retourneert "MSK" of "+04:00" voor Moskou-tijd, bijvoorbeeld, er is (of was) een MySQL-bug waarbij, indien ingesteld op een numerieke offset, de zomertijd niet zou worden aangepast

Om de huidige tijdzone te krijgen

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

Het zal 02:00:00 terugkeren als uw tijdzone +2:00 is.

Om de huidige UNIX-tijdstempel te krijgen (in seconden):

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

Om de tijdstempelkolom als UNIX-tijdstempel te krijgen

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

Om een ​​UTC datetime-kolom als UNIX-tijdstempel te krijgen

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

Verkrijg een huidige tijdzone datetime van een positief UNIX-tijdstempel integer

SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`

Krijg een UTC datetime van een UNIX-tijdstempel

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

Krijg een huidige tijdzone datetime van een negatief UNIX-tijdstempel integer

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

Er zijn 3 plaatsen waar de tijdzone kan worden ingesteld in MySQL:

Let op:Een tijdzone kan in 2 formaten worden ingesteld:

  1. een offset van UTC:'+00:00', '+10:00' of '-6:00'
  2. als een benoemde tijdzone:'Europe/Helsinki', 'US/Eastern' of 'MET'

Benoemde tijdzones kunnen alleen worden gebruikt als de tabellen met tijdzone-informatie in de mysql-database zijn gemaakt en ingevuld.

in het bestand "my.cnf"

default_time_zone='+00:00'

of

timezone='UTC'

@@global.time_zone variabele

Om te zien op welke waarde ze zijn ingesteld

SELECT @@global.time_zone;

Gebruik een van beide om er een waarde voor in te stellen:

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

@@session.time_zone variabele

SELECT @@session.time_zone;

Gebruik een van beide om het in te stellen:

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

zowel "@@global.time_zone variabele" als "@@session.time_zone variabele" kunnen "SYSTEM" retourneren, wat betekent dat ze de tijdzone gebruiken die is ingesteld in "my.cnf".

Om tijdzonenamen te laten werken (zelfs voor standaardtijdzone), moet u uw tijdzone-informatietabellen instellen die moeten worden ingevuld: http://dev.mysql.com/doc /refman/5.1/en/time-zone-support.html

Opmerking:u kunt dit niet doen omdat het NULL teruggeeft:

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

Mysql-tijdzonetabellen instellen

Voor CONVERT_TZ om te werken, moeten de tijdzonetabellen worden ingevuld

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

Als ze leeg zijn, vul ze dan op door deze opdracht uit te voeren

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

als deze opdracht je de foutmelding "gegevens te lang geeft voor kolom 'afkorting' op rij 1 ", dan kan dit worden veroorzaakt doordat er een NULL-teken wordt toegevoegd aan het einde van de tijdzone-afkorting

de oplossing is om dit uit te voeren

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

(zorg ervoor dat de dst-regels van uw servers up-to-date zijn zdump -v Europe/Moscow | grep 2011 https://chrisjean.com/updating-daylight-saving-time- on-linux/ )

Bekijk de volledige DST-overgangsgeschiedenis (zomertijd) voor elke tijdzone

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 past ook eventuele noodzakelijke zomertijdwijzigingen toe op basis van de regels in de bovenstaande tabellen en de datum die u gebruikt.

Opmerking:
Volgens de docs , verandert de waarde die u instelt voor time_zone niet, als u deze bijvoorbeeld instelt als "+01:00", dan wordt de time_zone ingesteld als een offset van UTC, die niet volgt op DST, dus het blijft allemaal hetzelfde het hele jaar door.

Alleen de genoemde tijdzones verandert de tijd tijdens de zomertijd.

Afkortingen zoals CET zal altijd een wintertijd zijn en CEST zal zomertijd zijn terwijl +01:00 altijd UTC zal zijn tijd + 1 uur en beide veranderen niet met DST.

Het system timezone is de tijdzone van de hostcomputer waarop mysql is geïnstalleerd (tenzij mysql deze niet kan bepalen)

U kunt hier meer lezen over het werken met DST.

Wanneer u UTC van de legendarische Jon Skeet niet moet gebruiken:https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (Bijvoorbeeld een geplande gebeurtenis in de toekomst die een tijd vertegenwoordigt, niet een moment in de tijd)

gerelateerde vragen:

Bronnen:



  1. Interval converteren naar minuten

  2. Wat is het equivalent van Oracle's REF CURSOR in MySQL bij gebruik van JDBC?

  3. Hoe u SQL Server-gebeurtenissen vastlegt en analyseert

  4. Een schemagebonden opgeslagen procedure maken in SQL Server