Как скопировать таблицы с одного сайта на другой с помощью php? - PullRequest
1 голос
/ 29 марта 2010

У меня есть 2 веб-сайта, скажем, - example.com и example1.com

example.com имеет базу данных fruits, в которой есть таблица apple с 7000 записями.

Я экспортировал apple и пытался импортировать его на example1.com, но всегда получаю «MYSQL Server удалился» Я подозреваю, что это связано с некоторыми ограничениями на стороне сервера.

Итак, как я могу скопировать таблицы, не обращаясь к системным администраторам? Есть ли способ сделать это с помощью PHP? Я прошел пример копирования таблиц, но это было в той же базе данных.

Оба example.com и example1.com находятся на одном сервере.

Ответы [ 3 ]

3 голосов
/ 29 марта 2010

Один из возможных подходов:

  1. На «исходном» сервере создайте сценарий PHP («экспортер»), который выводит содержимое таблицы в удобном для анализа формате (XML приходит на ум как легко генерировать и использовать, но есть альтернативы). как мог бы CSV).

  2. На «целевом» сервере создайте «импортирующий» PHP-скрипт, который запрашивает экспортный через HTTP, анализирует результат и использует эти данные для заполнения таблицы.

Это довольно обобщенно, но вам стоит начать. Вот некоторые соображения:

  • http://ie2.php.net/manual/en/function.http-request.php твой друг
  • Если таблица содержит конфиденциальные данные, существует множество методов повышения безопасности (http_request не предоставит вам прямую поддержку https: //, но вы можете зашифровать экспортируемые данные и расшифровать их при импорте: ищите «SSL» в руководство по PHP для более подробной информации).
  • Вам следует подумать о добавлении некоторой избыточности (или даже полноценного шифрования), чтобы предотвратить подделку данных во время их перемещения по сети между серверами.
  • Вы можете использовать параметры GET для повышения гибкости (например, передача имени таблицы в качестве параметра позволит вам иметь один сценарий для всех таблиц, которые вам, возможно, понадобится передать).
  • При больших таблицах тайм-ауты PHP могут играть против вас. Идеальным решением для этого был бы эффективный код + настраиваемое время ожидания для сценариев экспорта и импорта, но я даже не уверен, возможно ли это вообще. Очень надежный обходной путь - выполнять работу порциями (здесь вам пригодятся параметры GET, чтобы сообщить экспортеру, какой блок вам нужен, и специальной записи на выходе может быть достаточно, чтобы сообщить импортеру, сколько осталось импортировать). Перенаправления очень помогают при таком подходе (каждое перенаправление - это новый запрос к серверам, поэтому таймауты сбрасываются).

Может быть, я чего-то упускаю, но я надеюсь, что там достаточно, чтобы вы могли испачкать руки на работе и вернуться к любой конкретной проблеме, которую я мог не предвидеть.

Надеюсь, это поможет.


EDIT: К сожалению, я упустил детали, что обе базы данных находятся на одном сервере. В этом случае вы можете объединить задачу импорта и экспорта в один скрипт. Это означает, что:

  • Вам не нужен формат передачи (такой как XML или CSV): достаточно представления в памяти в PHP, поскольку теперь обе задачи выполняются в одном и том же сценарии.
  • Данные никогда не покидают ваш сервер, поэтому необходимость в шифровании не так велика. Просто убедитесь, что никто другой не сможет запустить ваш скрипт (с помощью аутентификации или аналогичных методов), и у вас все будет хорошо.
  • Тайм-ауты не столь ограничительны, так как вы не тратите много времени на ожидание ответа от источника на сервер назначения, но они все еще применяются. Параметры обработки фрагментов, перенаправления и GET (передаваемые в Location для перенаправления) по-прежнему являются хорошим решением, но вы можете сжать их намного ближе к тайм-ауту, поскольку метрики времени выполнения гораздо более надежны, чем метрики передачи данных между серверами.

Вот очень грубый набросок того, что вам может понадобиться кодировать:

$link_src = mysql_connect(source DB connection details);
$link_dst = mysql_connect(destination DB connection details);
/* You may want to truncate the table on destination before going on, to prevent data repetition */
$q = "INSERT INTO `table_name_here` (column_list_here) VALUES ";
$res = mysql_query("SELECT * FROM `table_name_here`", $link_src);
while ($row = mysql_fetch_assoc($res)) {
    $q = $q . sprintf("(%s, %s, %s), ", $row['field1_name'], $row['field2_name'], $row['field3_name']);
}
mysql_free_result($res);
/* removing the trailing ',' from $q is left as an exercise (ok, I'm lazy, but that's supposed to be just a sketck) */
mysql_query($q, $link_dst);

Вам нужно будет добавить логики чанкинга (они слишком специфичны для конкретного случая и настройки) и, возможно, вывести какое-то подтверждающее сообщение (возможно, DESCRIBE и COUNT таблиц источника и назначения и сравнение между ними). ?), но это довольно суть работы. В качестве альтернативы вы можете запустить отдельную вставку для каждой строки (вызывая запрос в цикле), но я уверен, что один запрос будет быстрее (однако, если у вас слишком малые ограничения ОЗУ для PHP, эта альтернатива позволяет вам получить избавиться от жажды памяти $q).


Еще одно редактирование:

Из ссылки на документацию, опубликованной Роберто:

Вы также можете получить эти ошибки, если отправите запрос на сервер, который является неправильным или слишком большим.Если mysqld получает пакет, который слишком велик или не в порядке, он предполагает, что с клиентом что-то не так, и закрывает соединение.Если вам нужны большие запросы (например, если вы работаете с большими BLOB-столбцами), вы можете увеличить лимит запросов, установив переменную max_allowed_packet сервера, значение которой по умолчанию составляет 1 МБ.Вам также может понадобиться увеличить максимальный размер пакета на стороне клиента.Более подробная информация о настройке размера пакета приведена в разделе B.5.2.10, «Пакет слишком большой».

Оператор INSERT или REPLACE, который вставляет большое количество строк, также может вызывать подобные ошибки.Любой из этих операторов отправляет серверу один запрос независимо от количества вставляемых строк;таким образом, вы часто можете избежать ошибки, уменьшив количество строк, отправляемых за INSERT или REPLACE.

Если это и является причиной вашей проблемы (и по вашему вопросу это кажется очень вероятнымэто так), тогда подход разбиения INSERT на один запрос на строку, скорее всего, решит ее.В этом случае приведенный выше эскиз кода выглядит так:

$link_src = mysql_connect(source DB connection details);
$link_dst = mysql_connect(destination DB connection details);
/* You may want to truncate the table on destination before going on, to prevent data repetition */
$q = "INSERT INTO `table_name_here` (column_list_here) VALUES ";
$res = mysql_query("SELECT * FROM `table_name_here`", $link_src);
while ($row = mysql_fetch_assoc($res)) {
    $q = $q . sprintf("INSERT INTO `table_name_here` (`field1_name`, `field2_name`, `field3_name`) VALUE (%s, %s, %s)", $row['field1_name'], $row['field2_name'], $row['field3_name']);
}
mysql_free_result($res);

Проблема также может быть вызвана огромным объемом исходного SELECT;в таком случае вы должны объединить это с разбивкой на блоки (либо с несколькими блоками SELECT + while (), извлечением прибыли из предложения LIMIT SQL, или с помощью перенаправлений), тем самым разбив SELECT на несколько небольших запросов. (Обратите внимание, что перенаправление на основе необходимо только в том случае, если у вас есть проблемы с тайм-аутом, или ваше время выполнения становится достаточно близким к тайм-ауту, чтобы угрожать проблемами в случае роста таблицы. В любом случае, это может быть хорошей идеей для реализации,даже если ваша таблица когда-либо вырастет до непристойного размера, скрипт все равно будет работать без изменений.)

1 голос
/ 30 марта 2010

Поработав некоторое время с этим, наткнулся на BigDump . Оно работало завораживающе! Был в состоянии скопировать большие базы данных без сбоев.

0 голосов
/ 29 марта 2010

Здесь приведены наиболее распространенные причины ошибки «MySQL Server исчез» в MySQL 5.0:

http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

Возможно, вы захотите взглянуть на это ииспользуйте его в качестве контрольного списка, чтобы увидеть, что вы делаете что-то не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...