Если в логах или базе данных время «уехало» на несколько часов, а PHP-скрипты и сервер показывают разные значения — дело в настройках временных зон. Эта несостыковка может сбить с толку при отладке, мешать аналитике и ломать расписания задач CRON. Разберёмся, почему MySQL и PHP живут «в разных часовых поясах» и как это исправить раз и навсегда.
Введение
Работа с датами и временем — одна из тех задач, где даже опытные разработчики иногда спотыкаются. Особенно когда на одном сервере установлены PHP и MySQL, а время в базе данных «уезжает» на несколько часов вперёд или назад. В логах события происходят «в будущем», заказы фиксируются не в тот момент, а CRON-задачи запускаются не тогда, когда нужно. Всё выглядит как баг, но на деле причина почти всегда одна — рассинхронизация временных зон.
MySQL, PHP и операционная система по-разному трактуют понятие текущего времени. Каждый компонент может жить в своём часовом поясе: сервер — по UTC, PHP — по локальному времени, а MySQL — вовсе по умолчанию в другой зоне. Если не привести их к единому стандарту, данные в таблицах и отчётах начинают «плыть», что особенно критично для проектов, где важна точность: интернет-магазинов, CRM-систем, аналитических платформ.
В этой статье мы подробно разберём, почему MySQL показывает одно время, а PHP — другое, как проверить текущие настройки на сервере и что именно нужно изменить, чтобы всё совпадало. Вы узнаете, как задать временную зону в конфигурации MySQL, как синхронизировать её с PHP и как избежать ошибок при переносе сайтов между серверами с разными часовыми поясами.
После прочтения у вас будет чёткий, рабочий алгоритм: от диагностики до полной синхронизации времени — чтобы все логи, заказы и отчёты отражали реальную картину, без смещений и сюрпризов.
В чём суть проблемы
MySQL, PHP и операционная система хранят и интерпретируют время по-разному.
По умолчанию:
- ОС сервера (например, Ubuntu) задаёт системную часовую зону.
- PHP использует ту, что указана в php.ini или установлена функцией date_default_timezone_set().
- MySQL берёт значение из своих настроек и не всегда подхватывает время системы.
Именно поэтому при выполнении запроса:
SELECT NOW();
Вы можете увидеть, что MySQL показывает, например, 2025-10-08 09:15:00,
а PHP — 2025-10-08 12:15:00. Разница в три часа — классическая ситуация, когда MySQL работает по UTC, а PHP — по местному времени сервера (например, Europe/Moscow).
Как проверить, что происходит
- Проверим системное время:
date
- Посмотрим настройки PHP (через консоль или phpinfo):
php -r "echo date('Y-m-d H:i:s');"
- Проверим, что думает MySQL:
SELECT NOW(), @@global.time_zone, @@session.time_zone;
Если увидите SYSTEM или +00:00, значит, MySQL живёт по UTC и не синхронизирован с системой.
Как задать правильную часовую зону MySQL
Есть два способа — временный (для текущей сессии) и постоянный (в конфигурации).
Временно (до перезапуска MySQL)
Выполните под пользователем root:
SET GLOBAL time_zone = '+03:00';
или
SET GLOBAL time_zone = 'Europe/Moscow';
Проверьте:
SELECT NOW();
Если время совпадает с PHP — всё верно.
Постоянно (в конфигурации MySQL)
Откройте файл конфигурации, обычно /etc/mysql/my.cnf или /etc/my.cnf:
[mysqld]
default_time_zone = '+03:00'
или используйте региональный формат:
[mysqld]
default_time_zone = 'Europe/Moscow'
После сохранения перезапустите сервер MySQL:
sudo systemctl restart mysql
Как синхронизировать PHP и MySQL
Чтобы всё работало согласованно, убедитесь, что системное время и таймзона сервера установлены верно:
sudo timedatectl set-timezone Europe/Moscow
В PHP задайте ту же зону:
date_default_timezone_set('Europe/Moscow');
или в php.ini:
date.timezone = "Europe/Moscow"
В MySQL пропишите тот же параметр default_time_zone.
Теперь данные в логах, базе и коде будут синхронизированы по времени.
Почему важно настроить всё правильно
Несовпадение временных зон может вызвать:
- смещение расписания CRON-задач;
- некорректное отображение времени заказов или логов;
- путаницу при синхронизации данных между сервисами;
- ошибки при работе с timestamp и datetime в приложениях.
Особенно это критично для систем аналитики, CRM и интернет-магазинов, где точное время записи важно для отчётности и расчёта заказов.
Советы для работы с временными зонами
- Всегда храните время в базе в UTC, а при отображении конвертируйте в нужный пояс на уровне приложения.
- Для Docker-контейнеров не забудьте монтировать /etc/localtime и /etc/timezone.
- Проверяйте, чтобы MySQL, PHP и cron имели одинаковую зону.
- Используйте CONVERT_TZ() для явного перевода времени между часовыми поясами.
Вывод
Если MySQL показывает не то время, что PHP, — это не ошибка сервера, а несогласованные настройки. Приведите временные зоны всех компонентов к одному значению — и избавьтесь от хаоса в логах и базе данных.
Проверить всё можно одной строкой:
SELECT NOW(), @@global.time_zone, @@session.time_zone;
Если видите нужный пояс и совпадение с PHP, значит, порядок восстановлен.
Читайте в блоге:
- Ошибка «Another MySQL daemon already running with the same unix socket»: когда возникает и как её исправить
- Оптимизация базы данных OpenCart: как очистить магазин и ускорить MySQL
- Как перенести каталог данных MySQL на другой диск в Ubuntu 24.04