2008-08-25 4 views
403

Без локального доступа к серверу существует ли способ дублировать/клонировать MySQL db (с содержимым и без содержимого) в другой, не используя mysqldump?Копирование/дублирование базы данных без использования mysqldump

В настоящее время я использую MySQL 4.0.

+12

Что не так с `mysqldump`? – 2011-06-29 21:06:52

ответ

129

Вы можете дублировать таблицу без данных, выполнив:

CREATE TABLE x LIKE y; 

(См MySQL CREATE TABLE Docs)

Вы можете написать скрипт, который принимает выходной сигнал из SHOW TABLES из одной базы данных и копирует схемы в другой. Вы должны иметь возможность ссылаться на имена схем + таблицы, как:

CREATE TABLE x LIKE other_db.y; 

Насколько идет данные, вы также можете сделать это в MySQL, но это не обязательно быстро. После того как вы создали ссылки, вы можете выполнить следующую команду, чтобы скопировать данные:

INSERT INTO x SELECT * FROM other_db.y; 

Если вы используете MyISAM, вы лучше скопировать файлы таблиц; это будет намного быстрее. Вы должны быть в состоянии сделать то же самое, если используете INNODB с per table table spaces.

Если вы делаете INSERT INTO SELECT, обязательно временно turn off indexes с ALTER TABLE x DISABLE KEYS!

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

+1

is эта работа для дублирования таблицы? так как я вижу, что команда CREATE TABLE – GusDeCooL 2011-06-27 12:13:53

57

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

#!/bin/bash 

DBUSER=user 
DBPASSWORD=pwd 
DBSNAME=sourceDb 
DBNAME=destinationDb 
DBSERVER=db.example.com 

fCreateTable="" 
fInsertData="" 
echo "Copying database ... (may take a while ...)" 
DBCONN="-h ${DBSERVER} -u ${DBUSER} --password=${DBPASSWORD}" 
echo "DROP DATABASE IF EXISTS ${DBNAME}" | mysql ${DBCONN} 
echo "CREATE DATABASE ${DBNAME}" | mysql ${DBCONN} 
for TABLE in `echo "SHOW TABLES" | mysql $DBCONN $DBSNAME | tail -n +2`; do 
     createTable=`echo "SHOW CREATE TABLE ${TABLE}"|mysql -B -r $DBCONN $DBSNAME|tail -n +2|cut -f 2-` 
     fCreateTable="${fCreateTable} ; ${createTable}" 
     insertData="INSERT INTO ${DBNAME}.${TABLE} SELECT * FROM ${DBSNAME}.${TABLE}" 
     fInsertData="${fInsertData} ; ${insertData}" 
done; 
echo "$fCreateTable ; $fInsertData" | mysql $DBCONN $DBNAME 
+0

Это также скопирует данные ограничения и другие свойства таблиц? – 2011-04-08 10:54:06

+1

Кажется, так, потому что он использует инструкцию «SHOW CREATE TABLE», которая генерирует CREATE TABLE со всеми свойствами оригинала. – Danita 2011-05-06 15:34:14

+0

Это я или это не работает? Он создал всего несколько таблиц и выбрал это: Копирование базы данных (...) ERROR 1064 (42000) в строке 1: У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с '-modelowanie-copy' в строке 1 ERROR 1064 (42000) в строке 1: у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с '-modelowanie-copy' в строке 1 – zirael 2011-10-14 10:35:33

676

я могу вы сказали, что не хотите использовать mysqldump, но я дошел до этой страницы, ища аналогичное решение, а другие могут найти его. Имея это в виду, здесь приведен простой способ дублирования базы данных из командной строки сервера Windows:

  1. Создайте целевую базу данных с использованием MySQLAdmin или вашего предпочтительного метода. В этом примере db2 является целевой базой данных, в которой будет скопирована исходная база данных db1.
  2. Выполните следующую инструкцию в командной строке:

mysqldump -h [server] -u [user] -p[password] db1 | mysql -h [server] -u [user] -p[password] db2

Примечание: Там нет НИКАКОГО пространства между -p и [password]

11

В PHP:

function cloneDatabase($dbName, $newDbName){ 
    global $admin; 
    $db_check = @mysql_select_db ($dbName); 
    $getTables = $admin->query("SHOW TABLES"); 
    $tables = array(); 
    while($row = mysql_fetch_row($getTables)){ 
     $tables[] = $row[0]; 
    } 
    $createTable = mysql_query("CREATE DATABASE `$newDbName` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;") or die(mysql_error()); 
    foreach($tables as $cTable){ 
     $db_check = @mysql_select_db ($newDbName); 
     $create  = $admin->query("CREATE TABLE $cTable LIKE ".$dbName.".".$cTable); 
     if(!$create) { 
      $error = true; 
     } 
     $insert  = $admin->query("INSERT INTO $cTable SELECT * FROM ".$dbName.".".$cTable); 
    } 
    return !isset($error); 
} 


// usage 
$clone = cloneDatabase('dbname','newdbname'); // first: toCopy, second: new database 
0

Я не знаю, что вы подразумеваете под «локальным доступом». Но для этого решения вам необходимо иметь доступ к ssh серверу до копировать файлы, в которых хранится база данных.

Я не могу использовать mysqldump, потому что моя база данных большая (7Go, mysqldump fail) Если версия базы данных mysql слишком разная, она может не работать, вы можете проверить свою версию mysql с помощью mysql -V.

1) Скопируйте данные с удаленного сервера на локальный компьютер (VPS это псевдоним к удаленному серверу, может быть заменен [email protected])

ssh vps:/etc/init.d/mysql stop 
scp -rC vps:/var/lib/mysql/ /tmp/var_lib_mysql 
ssh vps:/etc/init.d/apache2 start 

2) Импорт данных скопированные на локальном компьютере

/etc/init.d/mysql stop 
sudo chown -R mysql:mysql /tmp/var_lib_mysql 
sudo nano /etc/mysql/my.cnf 
-> [mysqld] 
-> datadir=/tmp/var_lib_mysql 
/etc/init.d/mysql start 

Если у вас есть другая версия, вам может понадобиться запустить

/etc/init.d/mysql stop 
mysql_upgrade -u root -pPASSWORD --force #that step took almost 1hrs 
/etc/init.d/mysql start 
0

Лучший способ клонировать таблицы базы данных без mysqldump:

  1. Создайте новую базу данных.
  2. Создание клонов-запросов с запросом:

    SET @NewSchema = 'your_new_db'; 
    SET @OldSchema = 'your_exists_db'; 
    SELECT CONCAT('CREATE TABLE ',@NewSchema,'.',table_name, ' LIKE ', TABLE_SCHEMA ,'.',table_name,';INSERT INTO ',@NewSchema,'.',table_name,' SELECT * FROM ', TABLE_SCHEMA ,'.',table_name,';') 
    FROM information_schema.TABLES where TABLE_SCHEMA = @OldSchema AND TABLE_TYPE != 'VIEW'; 
    
  3. Выполнить этот вывод!

Но обратите внимание, сценарий выше всего быстрый клон таблиц - не представления, триггеры и пользовательские функции: вы можете быстро получить структуру с помощью mysqldump --no-data --triggers -uroot -ppassword, а затем использовать для клонирования только вставить заявление.

Почему это актуальный вопрос? Потому что загрузка mysqldumps является уродливой медленной, если DB превышает 2Gb. И вы не можете клонировать таблицы InnoDB, просто копируя файлы DB (например, резервное копирование моментальных снимков).

0

Все предыдущие решения немного поразмыслив, однако они просто не копируют все. Я создал функцию PHP (хотя и несколько длинную), которая копирует все, включая таблицы, внешние ключи, данные, представления, процедуры, функции, триггеры и события. Вот код:

/* This function takes the database connection, an existing database, and the new database and duplicates everything in the new database. */ 
function copyDatabase($c, $oldDB, $newDB) { 

    // creates the schema if it does not exist 
    $schema = "CREATE SCHEMA IF NOT EXISTS {$newDB};"; 
    mysqli_query($c, $schema); 

    // selects the new schema 
    mysqli_select_db($c, $newDB); 

    // gets all tables in the old schema 
    $tables = "SELECT table_name 
       FROM information_schema.tables 
       WHERE table_schema = '{$oldDB}' 
       AND table_type = 'BASE TABLE'"; 
    $results = mysqli_query($c, $tables); 

    // checks if any tables were returned and recreates them in the new schema, adds the foreign keys, and inserts the associated data 
    if (mysqli_num_rows($results) > 0) { 

     // recreates all tables first 
     while ($row = mysqli_fetch_array($results)) { 
      $table = "CREATE TABLE {$newDB}.{$row[0]} LIKE {$oldDB}.{$row[0]}"; 
      mysqli_query($c, $table); 
     } 

     // resets the results to loop through again 
     mysqli_data_seek($results, 0); 

     // loops through each table to add foreign key and insert data 
     while ($row = mysqli_fetch_array($results)) { 

      // inserts the data into each table 
      $data = "INSERT IGNORE INTO {$newDB}.{$row[0]} SELECT * FROM {$oldDB}.{$row[0]}"; 
      mysqli_query($c, $data); 

      // gets all foreign keys for a particular table in the old schema 
      $fks = "SELECT constraint_name, column_name, table_name, referenced_table_name, referenced_column_name 
        FROM information_schema.key_column_usage 
        WHERE referenced_table_name IS NOT NULL 
        AND table_schema = '{$oldDB}' 
        AND table_name = '{$row[0]}'"; 
      $fkResults = mysqli_query($c, $fks); 

      // checks if any foreign keys were returned and recreates them in the new schema 
      // Note: ON UPDATE and ON DELETE are not pulled from the original so you would have to change this to your liking 
      if (mysqli_num_rows($fkResults) > 0) { 
       while ($fkRow = mysqli_fetch_array($fkResults)) { 
        $fkQuery = "ALTER TABLE {$newDB}.{$row[0]}        
           ADD CONSTRAINT {$fkRow[0]} 
           FOREIGN KEY ({$fkRow[1]}) REFERENCES {$newDB}.{$fkRow[3]}({$fkRow[1]}) 
           ON UPDATE CASCADE 
           ON DELETE CASCADE;"; 
        mysqli_query($c, $fkQuery); 
       } 
      } 
     } 
    } 

    // gets all views in the old schema 
    $views = "SHOW FULL TABLES IN {$oldDB} WHERE table_type LIKE 'VIEW'";     
    $results = mysqli_query($c, $views); 

    // checks if any views were returned and recreates them in the new schema 
    if (mysqli_num_rows($results) > 0) { 
     while ($row = mysqli_fetch_array($results)) { 
      $view = "SHOW CREATE VIEW {$oldDB}.{$row[0]}"; 
      $viewResults = mysqli_query($c, $view); 
      $viewRow = mysqli_fetch_array($viewResults); 
      mysqli_query($c, preg_replace("/CREATE(.*?)VIEW/", "CREATE VIEW", str_replace($oldDB, $newDB, $viewRow[1]))); 
     } 
    } 

    // gets all triggers in the old schema 
    $triggers = "SELECT trigger_name, action_timing, event_manipulation, event_object_table, created 
       FROM information_schema.triggers 
       WHERE trigger_schema = '{$oldDB}'";     
    $results = mysqli_query($c, $triggers); 

    // checks if any triggers were returned and recreates them in the new schema 
    if (mysqli_num_rows($results) > 0) { 
     while ($row = mysqli_fetch_array($results)) { 
      $trigger = "SHOW CREATE TRIGGER {$oldDB}.{$row[0]}"; 
      $triggerResults = mysqli_query($c, $trigger); 
      $triggerRow = mysqli_fetch_array($triggerResults); 
      mysqli_query($c, str_replace($oldDB, $newDB, $triggerRow[2])); 
     } 
    } 

    // gets all procedures in the old schema 
    $procedures = "SHOW PROCEDURE STATUS WHERE db = '{$oldDB}'"; 
    $results = mysqli_query($c, $procedures); 

    // checks if any procedures were returned and recreates them in the new schema 
    if (mysqli_num_rows($results) > 0) { 
     while ($row = mysqli_fetch_array($results)) { 
      $procedure = "SHOW CREATE PROCEDURE {$oldDB}.{$row[1]}"; 
      $procedureResults = mysqli_query($c, $procedure); 
      $procedureRow = mysqli_fetch_array($procedureResults); 
      mysqli_query($c, str_replace($oldDB, $newDB, $procedureRow[2])); 
     } 
    } 

    // gets all functions in the old schema 
    $functions = "SHOW FUNCTION STATUS WHERE db = '{$oldDB}'"; 
    $results = mysqli_query($c, $functions); 

    // checks if any functions were returned and recreates them in the new schema 
    if (mysqli_num_rows($results) > 0) { 
     while ($row = mysqli_fetch_array($results)) { 
      $function = "SHOW CREATE FUNCTION {$oldDB}.{$row[1]}"; 
      $functionResults = mysqli_query($c, $function); 
      $functionRow = mysqli_fetch_array($functionResults); 
      mysqli_query($c, str_replace($oldDB, $newDB, $functionRow[2])); 
     } 
    } 

    // selects the old schema (a must for copying events) 
    mysqli_select_db($c, $oldDB); 

    // gets all events in the old schema 
    $query = "SHOW EVENTS 
       WHERE db = '{$oldDB}';"; 
    $results = mysqli_query($c, $query); 

    // selects the new schema again 
    mysqli_select_db($c, $newDB); 

    // checks if any events were returned and recreates them in the new schema 
    if (mysqli_num_rows($results) > 0) { 
     while ($row = mysqli_fetch_array($results)) { 
      $event = "SHOW CREATE EVENT {$oldDB}.{$row[1]}"; 
      $eventResults = mysqli_query($c, $event); 
      $eventRow = mysqli_fetch_array($eventResults); 
      mysqli_query($c, str_replace($oldDB, $newDB, $eventRow[3])); 
     } 
    } 
}