Временной сдвиг в phpMyAdmin

версия для печати

Продолжаю тему "временных аномалий" в MySQL :) У меня с хостером разные часовые пояса: у него - GMT+3:00, а на моих сайтах GMT+8:00 (об этом на сайтах скрипты заботятся). Добавлять новости на сайт это не мешает, т.к. время пишется через mysql-функцию now() (текущее значение времени). Проблема появляется, когда мне нужна синхронизация записей с локальной копией БД. Делаю следующее: через phpMyAdmin экспортирую БД в файл - dump.sql, потом загружаю его на своем (местном) сервере MySQL. После такой синхронизации я получаю разницу во времени в 5 часов в каждой записи, где вообще есть время. Покопался и нашел причину! :)

Отступление: согласно документации MySQL, при записи времени в базу его значение сначала переводится в абсолютное UTC-значение (timestamp), потом пишется. Об этом написано где-то здесь (eng). Такой подход ко времени позволяет обойти разногласия часовых поясов при записи. Другими словами, когда я использую функцию now(), то в БД пишется текущее время по Гринвичу (GMT 0:00) в формате timestamp, не зависимо от того, какой часовой пояс у mysql-сессии/сервера.

Итак, проблема.. При экспорте phpMyAdmin сочиняет sql-файл, читая записи в БД:

Файл dump.sql
-- phpMyAdmin SQL Dump
-- version 3.2.3
...
-- Дамп данных таблицы `table`
REPLACE INTO `table` VALUES(38, '2011-08-05 19:11:59', 1, NULL, 'La peau de chagrin' ...);
REPLACE INTO `table` VALUES(39, '2011-08-12 03:41:15', 1, NULL, 'Blitz'...);

В этом файле в полях времени стоят уже конкретные форматированные дата/время, а не их UTC-значение. И они сдвинуты на GMT+3:00 часа! Это происходит потому, что при чтении из БД UTC-значение времени преобразуется в читабельную дату/время с учетом часового пояса mysql-сессии/сервера (см. тот же мануал по MySQL). Все даже еще интереснее: в БД по-прежнему хранится точное UTC-время записи, но в дамп оно не попадает, т.к. файл собирается на основании SELECT-запросов, в которые (заботами MySQL) пишется дата со сдвигом, вместо точного timestamp-числа. В итоге, при запуске такого sql-дампа на локальном сервере я получаю сдвиг по времени на -5 часов от настоящего времени записи! Еще круче получится, если я попытаюсь таким же способом (генерацией sql-файла), залить данные обратно на сервер хостера. Вообщем временные сдвиги и UTC-преобразования убивают синхронизацию.

Решение 1: в начале dump-файла добавить запрос с установкой временной зоны, такой же как на сервере хостера. Подробнее об этом читайте здесь: "Работа со временем в PHP/MySQL". В моем случае запрос выглядит так:

Подправленный файл dump.sql
SET SESSION time_zone = 'Europe/Moscow';
-- Далее, собственно дамп экспортируемой таблицы.
REPLACE INTO `table` VALUES(38, '2011-08-05 19:11:59', 1, NULL, 'La peau de chagrin' ...);
REPLACE INTO `table` VALUES(39, '2011-08-12 03:41:15', 1, NULL, 'Blitz'...);

Решение 2: написать свой инструмент sql-дампа. Допустим, тот же php-скрипт, выполняемый в переменных окружения сайта. Тогда в дамп пойдет время с учетом сдвига, определенного на сайте (совпадающего с "местным" временем), т.е. "правильное" время записи. В крайнем случае, можно в такой дамп-файл так же в начале писать запрос на смену часового пояса для сессии. Теоретически, код будет не сложный :) Но пока это все на уровне идеи.

Есть и другое решение, наверно: отказаться от phpMyAdmin и подключаться к БД другими клиентами. Но мой хостер дал мне доступ к БД только через phpMyAdmin. Цитирую "Доступ извне к базам данных по умолчанию запрещен. Но, если у вас статический ip-адрес и Вы укажете для чего Вам нужен доступ к БД извне, то вопрос будет рассмотрен и, в случае положительного его решения, доступ к базам данных Вам откроют."

[update: 26 августа 2011] Сделал свой Dumper! =) Все отлично работает в обе стороны. Перед сборкой дамп-файла для хостера сначала устанавливаю часовой пояс сессии, все запросы в скрипте выполняются с его учетом. Тогда не нужен лишний запрос в самом файле :)

[1oo%, EoF]


Похожие материалы: Работа со временем в PHP/MySQL
Понравилась статья? Расскажите о ней друзьям:

Метки: MySQL, кодинг

Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки