7.1.15 Поддержка часовых поясов в MySQL Server
В данном разделе описываются настройки часовых поясов в MySQL, как загрузить системные таблицы, необходимые для поддержки именованных часовых поясов, как следить за изменениями часовых поясов и как включить поддержку високосных секунд.
Также поддерживаются смещения часовых поясов для вставляемых значений datetime; см. Раздел 13.2.2, «Типы данных DATE, DATETIME и TIMESTAMP» для получения дополнительной информации.
Информация о настройках часовых поясов в конфигурациях репликации представлена в Разделе 19.5.1.14, «Репликация и системные функции» и Разделе 19.5.1.33, «Репликация и часовые пояса».
Переменные часовых поясов
MySQL Server поддерживает несколько настроек часовых поясов:
-
Системный часовой пояс сервера. При запуске сервер пытается определить часовой пояс хост-машины и использует его для установки системной переменной
system_time_zone.Чтобы явно указать системный часовой пояс для MySQL Server при запуске, установите переменную среды
TZперед запуском mysqld. Если вы запускаете сервер с помощью mysqld_safe, его опция--timezoneпредоставляет другой способ установки системного часового пояса. Допустимые значения дляTZи--timezoneзависят от операционной системы. Обратитесь к документации вашей операционной системы, чтобы узнать допустимые значения. -
Текущий часовой пояс сервера. Глобальная системная переменная
time_zoneуказывает часовой пояс, в котором сервер в данный момент работает. Начальное значениеtime_zoneравно'SYSTEM', что указывает на то, что часовой пояс сервера совпадает с системным часовым поясом.ПримечаниеЕсли установлено значение
SYSTEM, каждый вызов функции MySQL, требующий расчета часового пояса, выполняет системный вызов библиотеки для определения текущего системного часового пояса. Этот вызов может быть защищен глобальным мьютексом, что приводит к конкуренции.Начальное значение глобального часового пояса сервера можно явно указать при запуске с помощью опции
--default-time-zoneв командной строке или использовать следующую строку в файле параметров:default-time-zone='
timezone'Если у вас есть привилегия
SYSTEM_VARIABLES_ADMIN(или устаревшая привилегияSUPER), вы можете установить значение глобального часового пояса сервера во время выполнения с помощью этого оператора:SET GLOBAL time_zone =
timezone; -
Часовые пояса на сессионном уровне. У каждого подключенного клиента есть собственная настройка часового пояса сессии, заданная сессионной переменной
time_zone. Изначально сессионная переменная принимает значение из глобальной переменнойtime_zone, но клиент может изменить свой собственный часовой пояс с помощью этого оператора:SET time_zone =
timezone;
Настройка часового пояса сессии влияет на отображение и хранение значений времени, чувствительных к часовому поясу. Это включает значения, отображаемые функциями, такими как NOW() или CURTIME(), и значения, хранящиеся в столбцах TIMESTAMP и извлекаемые из них. Значения столбцов TIMESTAMP преобразуются из часового пояса сессии в UTC для хранения и из UTC в часовой пояс сессии для извлечения.
Настройка часового пояса сессии не влияет на значения, отображаемые функциями, такими как UTC_TIMESTAMP(), или значения в столбцах DATE, TIME или DATETIME. Значения этих типов данных также не хранятся в UTC; часовой пояс применяется к ним только при преобразовании из TIMESTAMP значений. Если вам нужна локализованная арифметика для DATE, TIME или DATETIME значений, преобразуйте их в UTC, выполните арифметические операции и затем преобразуйте обратно.
Текущие значения глобального и сессионного часовых поясов можно получить так:
SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;
Значения timezone могут быть заданы в нескольких форматах, ни один из которых не чувствителен к регистру:
Как значение
'SYSTEM', указывающее, что часовой пояс сервера совпадает с системным часовым поясом.-
Как строка, указывающая смещение от UTC в формате
[, префиксH]H:MM+или-, например,'+10:00','-6:00'или'+05:30'. Ведущий ноль для значений часов меньше 10 можно использовать необязательно; MySQL добавляет ведущий ноль при хранении и извлечении значения в таких случаях. MySQL преобразует'-00:00'или'-0:00'в'+00:00'.Это значение должно находиться в диапазоне от
'-13:59'до'+14:00'включительно. -
Как имя часового пояса, например,
'Europe/Helsinki','US/Eastern','MET'или'UTC'.ПримечаниеИменованные часовые пояса можно использовать только в том случае, если таблицы информации о часовых поясах в базе данных
mysqlбыли созданы и заполнены. В противном случае использование именованного часового пояса приведет к ошибке:mysql>
SET time_zone = 'UTC';ERROR 1298 (HY000): Unknown or incorrect time zone: 'UTC'
Заполнение таблиц часовых поясов
В схеме системы mysql существуют несколько таблиц для хранения информации о часовых поясах (см. раздел 7.3, «Схема mysql System»). Процедура установки MySQL создаёт таблицы часовых поясов, но не загружает их. Для их ручной загрузки воспользуйтесь следующими инструкциями.
Загрузка информации о часовых поясах не является одноразовой операцией, так как данные периодически обновляются. При таких изменениях приложения, использующие старые правила, устаревают, и вам может потребоваться перезагрузить таблицы часовых поясов, чтобы информация, используемая сервером MySQL, была актуальной. См. поддержание актуальности данных о часовых поясах.
Если ваша система имеет собственную базу данных zoneinfo (набор файлов, описывающих часовые поясы), используйте программу mysql_tzinfo_to_sql для загрузки таблиц часовых поясов. Примерами таких систем являются Linux, macOS, FreeBSD и Solaris. Вероятное местоположение этих файлов — каталог /usr/share/zoneinfo. Если у вашей системы нет базы данных zoneinfo, вы можете использовать загружаемый пакет, как описано далее в этом разделе.
Для загрузки таблиц часовых поясов из командной строки передайте путь к каталогу zoneinfo в программу mysql_tzinfo_to_sql и передайте вывод в программу mysql. Например:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Команда mysql предполагает подключение к серверу с использованием учетной записи, такой как root, имеющей права на изменение таблиц в схеме системы mysql. Настройте параметры подключения по мере необходимости.
Программа mysql_tzinfo_to_sql считывает файлы часовых поясов вашей системы и генерирует из них SQL-запросы. Программа mysql обрабатывает эти запросы для загрузки таблиц часовых поясов.
Программа mysql_tzinfo_to_sql также может использоваться для загрузки одного файла часового пояса или генерации информации о високосных секундах:
-
Для загрузки одного файла часового пояса
tz_file, соответствующего имени часового поясаtz_name, вызовите mysql_tzinfo_to_sql следующим образом:mysql_tzinfo_to_sql
tz_filetz_name| mysql -u root -p mysqlВ этом случае необходимо выполнить отдельные команды для загрузки файла часового пояса для каждого требуемого часового пояса.
-
Если ваш часовой пояс должен учитывать високосные секунды, инициализируйте информацию о високосных секундах следующим образом, где
tz_file— имя файла вашего часового пояса:mysql_tzinfo_to_sql --leap
tz_file| mysql -u root -p mysql
После выполнения mysql_tzinfo_to_sql перезапустите сервер, чтобы он не продолжал использовать кэшированные данные о часовых поясах.
Если у вашей системы нет базы данных zoneinfo (например, Windows), вы можете использовать пакет с SQL-запросами, доступный для скачивания в зоне разработчиков MySQL:
Не используйте загружаемый пакет часовых поясов, если у вашей системы есть база данных zoneinfo. Используйте утилиту mysql_tzinfo_to_sql вместо этого. В противном случае вы можете вызвать различие в обработке дат и времени между MySQL и другими приложениями вашей системы.
Для использования загруженного пакета SQL-запросов для часовых поясов распакуйте его, затем загрузите содержимое распакованного файла в таблицы часовых поясов:
mysql -u root -p mysql < file_name
Затем перезапустите сервер.
Не используйте загружаемый пакет часовых поясов, содержащий таблицы MyISAM. Он предназначен для более старых версий MySQL. MySQL теперь использует InnoDB для таблиц часовых поясов. Попытка заменить их таблицами MyISAM приведёт к проблемам.
Поддержание актуальности данных о часовых поясах
При изменении правил часовых поясов приложения, использующие старые правила, становятся устаревшими. Для поддержания актуальности необходимо убедиться, что ваша система использует актуальную информацию о часовых поясах. Для MySQL необходимо учитывать несколько факторов:
Время операционной системы влияет на значение времени, используемое сервером MySQL, если его часовой пояс установлен на
SYSTEM. Убедитесь, что ваша операционная система использует самую последнюю информацию о часовых поясах. Для большинства операционных систем последнее обновление или пакет обновления готовят вашу систему к изменениям во времени. Проверьте веб-сайт поставщика вашей операционной системы на наличие обновления, которое решает проблему с изменениями времени.Если вы замените системный файл часового пояса
/etc/localtimeна версию, использующую правила, отличающиеся от тех, которые действовали при запуске mysqld, перезапустите mysqld, чтобы он использовал обновлённые правила. В противном случае mysqld может не заметить изменений в времени системы.-
Если вы используете именованные часовые пояса с MySQL, убедитесь, что таблицы часовых поясов в базе данных
mysqlактуальны:Если у вашей системы есть собственная база данных zoneinfo, перезагружайте таблицы часовых поясов MySQL всякий раз, когда база данных zoneinfo обновляется.
Для систем, у которых нет собственной базы данных zoneinfo, проверяйте зону разработчиков MySQL на наличие обновлений. При доступности нового обновления скачайте его и используйте для замены содержимого текущих таблиц часовых поясов.
Инструкции для обоих методов см. в разделе о заполнении таблиц часовых поясов. mysqld кэширует информацию о часовых поясах, поэтому после обновления таблиц часовых поясов перезапустите mysqld, чтобы убедиться, что он не продолжает обслуживать устаревшие данные о часовых поясах.
Если вы не уверены, доступны ли именованные часовые пояса для использования в качестве часового пояса сервера или клиентами, установившими свой часовой пояс, проверьте, пусты ли ваши таблицы часовых поясов. Следующий запрос определяет, содержит ли таблица, содержащая имена часовых поясов, какие-либо строки:
mysql> SELECT COUNT(*) FROM mysql.time_zone_name;
+----------+
| COUNT(*) |
+----------+
| 0 |
+----------+
Счётчик нуль указывает, что таблица пуста. В этом случае ни одно приложение в настоящее время не использует именованные часовые пояса, и вам не нужно обновлять таблицы (если вы не хотите включить поддержку именованных часовых поясов). Счётчик, больший нуля, указывает, что таблица не пуста и её содержимое доступно для использования в поддержке именованных часовых поясов. В этом случае обязательно перезагрузите таблицы часовых поясов, чтобы приложения, использующие именованные часовые пояса, могли получить правильные результаты запросов.
Для проверки правильности обновления вашей установки MySQL для изменений правил летнего времени используйте подобный тест. Пример использует значения, соответствующие изменению летнего времени в США на 1 час в 2007 году, произошедшему 11 марта в 2 часа ночи.
Тест использует этот запрос:
SELECT
CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') AS time1,
CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') AS time2;
Два значения времени указывают на время, в которое происходит смена летнего времени, а использование именованных часовых поясов требует использования таблиц часовых поясов. Желаемый результат заключается в том, что оба запроса возвращают один и тот же результат (время входа, преобразованное в эквивалентное значение в часовом поясе «US/Central»).
Перед обновлением таблиц часовых поясов вы видите неправильный результат, подобный этому:
+---------------------+---------------------+
| time1 | time2 |
+---------------------+---------------------+
| 2007-03-11 01:00:00 | 2007-03-11 02:00:00 |
+---------------------+---------------------+
После обновления таблиц вы должны увидеть правильный результат:
+---------------------+---------------------+
| time1 | time2 |
+---------------------+---------------------+
| 2007-03-11 01:00:00 | 2007-03-11 01:00:00 |
+---------------------+---------------------+
Поддержка високосных секунд в часовых поясах
Значения високосных секунд возвращаются со временной частью, оканчивающейся на :59:59. Это означает, что такая функция, как NOW(), может возвращать одно и то же значение в течение двух или трёх последовательных секунд во время високосной секунды. Остаётся справедливым, что буквальные временные значения, имеющие временную часть, оканчивающуюся на :59:60 или :59:61, считаются некорректными.
Если необходимо найти значения TIMESTAMP за секунду до високосной секунды, могут быть получены аномальные результаты, если вы используете сравнение со значениями '. Следующий пример демонстрирует это. Он изменяет часовой пояс сессии на UTC, чтобы не было различия между внутренними значениями YYYY-MM-DD
hh:mm:ss'TIMESTAMP (которые находятся в UTC) и отображаемыми значениями (к которым применено исправление часового пояса).
mysql> CREATE TABLE t1 (
a INT,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ts)
);
Query OK, 0 rows affected (0.01 sec)
mysql> -- change to UTC
mysql> SET time_zone = '+00:00';
Query OK, 0 rows affected (0.00 sec)
mysql> -- Simulate NOW() = '2008-12-31 23:59:59'
mysql> SET timestamp = 1230767999;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (1);
Query OK, 1 row affected (0.00 sec)
mysql> -- Simulate NOW() = '2008-12-31 23:59:60'
mysql> SET timestamp = 1230768000;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (2);
Query OK, 1 row affected (0.00 sec)
mysql> -- values differ internally but display the same
mysql> SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;
+------+---------------------+--------------------+
| a | ts | UNIX_TIMESTAMP(ts) |
+------+---------------------+--------------------+
| 1 | 2008-12-31 23:59:59 | 1230767999 |
| 2 | 2008-12-31 23:59:59 | 1230768000 |
+------+---------------------+--------------------+
2 rows in set (0.00 sec)
mysql> -- only the non-leap value matches
mysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:59';
+------+---------------------+
| a | ts |
+------+---------------------+
| 1 | 2008-12-31 23:59:59 |
+------+---------------------+
1 row in set (0.00 sec)
mysql> -- the leap value with seconds=60 is invalid
mysql> SELECT * FROM t1 WHERE ts = '2008-12-31 23:59:60';
Empty set, 2 warnings (0.00 sec)
Чтобы обойти эту проблему, вы можете использовать сравнение, основанное на значении UTC, фактически хранящемся в столбце, к которому применено исправление високосной секунды:
mysql> -- selecting using UNIX_TIMESTAMP value return leap value
mysql> SELECT * FROM t1 WHERE UNIX_TIMESTAMP(ts) = 1230768000;
+------+---------------------+
| a | ts |
+------+---------------------+
| 2 | 2008-12-31 23:59:59 |
+------+---------------------+
1 row in set (0.00 sec)
© 2025 Oracle
Licensed under the GPLv2 License.