7.1.15 Поддержка часовых поясов MySQL Server
В этом разделе описываются настройки часовых поясов MySQL, как загрузить системные таблицы, необходимые для поддержки именованных часовых поясов, как следить за изменениями часовых поясов и как включить поддержку секунд високосных.
Также поддерживаются смещения часовых поясов для вставляемых значений datetime; см. Раздел 13.2.2, «Типы DATE, DATETIME и TIMESTAMP» для получения дополнительной информации.
Сведения о настройках часовых поясов в конфигурациях репликации см. в Разделе 19.5.1.14, «Репликация и системные функции» и Разделе 19.5.1.34, «Репликация и часовые пояса».
Переменные часовых поясов
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.