Синхронизация баз данных: local - server

Главные вкладки

Аватар пользователя beliy_snow beliy_snow 4 апреля 2007 в 14:48

Зачастую происходит так, что у сайта есть 2 версии: локальная (local) и лив-версия (server). Соответственно 2 базы данных, локальная и та, что на сервере лежит. Вы делаете какие-то изменения на локале и хотите перенести их на лив-сервер. Но вот незадача - с файлами все понятно, синхронизнул, переписал, неважно - а вот база. С базой будем разбираться отдельно...

Спустя какое-то время после работы сайта "вживую" база естесственно разрастается и каждый раз заливать перезаливать большие дампы становится не вариантом. Кто-то может сказать - вот, есть же специальные тулзы, которые заливают большие дампы. Хорошо, пользуйтесь, если удобно, я лично не привык, да и трафик резиновым бывает не всегда. Поэтому сегодня займемся следующим: будем собирать нужные и выкидывать ненужные запросы к локальной базе, чтобы потом, запустив небольшую порцию скриптов на лив-сервере, иметь все изменения, сделанные на локале. А, да, кто-то вспомнит модуль devel. Нравится - пользуйтесь, я не против Smile Поехали.

Откроем для начала файлик "includes/database.mysql.inc" и найдем там функцию _db_query(). Волшебная строчка здесь - <?php if (variable_get('dev_query', 0)) { ?> Она означает примерно следующее - попробуем взять переменную dev_query и если не найдем, то присвоим её значение 0. Чтобы долго не париться - можете прям в коде поставить 1, но, есть способ лучше! Открываем файл sites/default/settings.php и в самый конец дописываем: <?php $conf = array('dev_query' => 1); ?> Это сделано для того, чтобы в дальнейшем не залезая в код нативной функции можно было безболезненно все поменять обратно. Теперь все наши запросы лежат в глобальной переменной $queries. Для продвинутых дальше можно не читать Smile

Собираем запросы
Идем в код вашего модуля (если он есть), создаем 2 функции и радуемся жизни.
<?php function ваш_модуль_init() {
if (variable_get('dev_query', 0)) {
register_shutdown_function('ваш_модуль_shutdown');
}
}
function ваш_модуль_shutdown()
{
if (variable_get('dev_query', 0))
{
// подгружаем все наши запросы, которые были выполнены при загрузке страницы
global $queries;
// объявляем имя файла с учетом даты, чтобы потом не запутаться в километровых запросах
$filename = $_SERVER['DOCUMENT_ROOT'] . base_path() . "/db/queries_" . date("Y_m_d", time()) . ".txt";
// открываем, все такое
if (!$f_handle = fopen($filename, 'a+'))
{
echo "Cannot open file ($filename)"; exit();
}
fwrite($f_handle, date("Y-m-d H:i:s") . " Page: " . $_GET['q'] . "\n");
foreach ($queries as $k => $value)
{
$query_array = explode("\n", $value[0]);
$function = array_shift($query_array);
$query = implode("", $query_array);
// собираем запросы, которые содеражат директивы UPDATE, INSERT, REPLACE, DELETE и убираем запросы к cashe_menu, потому что если оставить, то невозможно будет листать файл
if ((preg_match("/^REPLACE/", $query, $mathes) || preg_match("/^UPDATE/", $query, $mathes) || preg_match("/^INSERT/", $query, $mathes) || preg_match("/^DELETE/", $query, $mathes)) && !preg_match("/cache_menu/", $query))
{
// я докучи добавил перевод timestamp и обычное время, чтобы читать было удобнее
if (preg_match("/(\d{10})/", $query, $match_date)) {
$replace = "'" . date("Y-m-d H:i:s", $match_date[0]) . " / " . $match_date[0] . "'";
$query = preg_replace("/(\d{10})/", $replace, $query);
}
if (fwrite($f_handle, $query . "\n") === FALSE)
echo "Cannot write to file";
}
}
fwrite($f_handle, "-----------------==============-----------------\n\n");
fclose($f_handle);
}
}
?>
Собственно все. Вы теперь всегда будете знать какие запросы на какой странице выполняются и зачем они выполняются.

Небольшое замечание к работе с таблицами cache и variables. Если вы увидели, что вдруг проскочил вот такой вот например запрос:
INSERT INTO variable (name, value) VALUES ('filter_default_format', 's:1:\"4\";');
После него необходимо выполнить следующий запрос:
DELETE FROM cache WHERE cid = 'variables';
По той причине, что переменные берутся из кеша - там же в кеше и останутся, а внесенные вами изменения не вступят в силу. Если же в таблице кеша запись с cid = variable пуста - друпал создаст её заново и изменения вступят в силу. По крайней мере я в это очень верю Smile

Комментарии

Аватар пользователя qman qman 7 апреля 2007 в 22:36

тема статьи интересная.
но не понял самого главного, где собраны скрипты c сервера разработчика, которые планируется запустить на интернет сервере?

Аватар пользователя beliy_snow beliy_snow 9 апреля 2007 в 16:02

Дак вот же:
<?php $filename = $_SERVER['DOCUMENT_ROOT'] . base_path() . "/db/queries_" . date("Y_m_d", time()) . ".txt";?>

Папочка db. В ней по датам все и будет лежать.

Аватар пользователя Влад Савицкий Влад Савицкий (не проверено) 23 августа 2007 в 1:17

Для меня тема актуальная, так как работаю в инете через CDMA телефон.
Синхронизация с сервером вещь не такая простая как вы описали.
Как вы решаете конфликты в базе данных?
Вручную?
Пользователь на сайте мог внести информацию и получить ID в таблице.
Такой же ID был привоен вашей информации на локалной машине...
Что делать?
Можно изменить номера вручную, а если это сдвигает все остальные данные и меняет связи?!!
Мне кажется, что это просто теоретическое упраженение или не до конца описанный метод.

Влад.

Аватар пользователя beliy_snow beliy_snow 11 сентября 2007 в 14:46

Вообще синхронизация сама по себе - процесс довольно сложный и болезненный, тем более если речь идет о базе данных.
По своему опыту могу сказать следующее:
1. По возможности нужно избегать влияния идентификаторов базы данных на код модулей. Другими словами не надо делать вот так define('MENU_ID', 10);
2. Время от времени производить глобальную синхронизацию в направлении Лив->Локал.

Описанный метод работал в самом начале, когда знаний о друпале не хватало, чтобы делать все "правильно". Сейчас это просто хороший инструмент для проверки того, что все работает так как надо, а не панацея от синхронизации.

Аватар пользователя qman qman 11 сентября 2007 в 21:46

итог то какой?
этим способом можно делать синхронизацию или успешный результат не всегда гарантированный?

Аватар пользователя beliy_snow beliy_snow 12 сентября 2007 в 11:04

Повторюсь. На нашем конкретном проекте данная схема синхронизации используется очень редко в силу следующих причин:
1) Основная настройка локальных версий и версий на сайтах произведена ранее.
2) Изменен подход к написанию модулей, в частности добавлена настройка нужных параметров (ранее задававшихся в ручную) из административной части.
3) При написании новых модулей используются инсталлы, которые создают нужные таблицы автоматически.

Отсюда следует, что на нашем конкретном проекте синхронизация заключается в полном переносе базы с лива на локал без потери настроек и полной работоспособности.

Посмотрите код, он полностью прозрачен, запустите, проверьте как это работает и сделайте свои выводы, ведь сколько проектов, столько и мнений.