Копировать / дублировать базу данных без использования mysqldump - PullRequest
417 голосов
/ 25 августа 2008

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

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

Ответы [ 9 ]

682 голосов
/ 18 августа 2011

Я вижу, вы сказали, что не хотите использовать 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]

нет пробела
133 голосов
/ 25 августа 2008

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

CREATE TABLE x LIKE y;

(см. MySQL CREATE TABLE Документы)

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

CREATE TABLE x LIKE other_db.y;

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

INSERT INTO x SELECT * FROM other_db.y;

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

Если вы в конечном итоге выполните INSERT INTO SELECT, обязательно временно отключите индексы с помощью ALTER TABLE x DISABLE KEYS!

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

58 голосов
/ 03 января 2010

Если вы используете Linux, вы можете использовать этот bash-скрипт: (возможно, требуется дополнительная очистка кода, но это работает ... и это намного быстрее, чем mysqldump | 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
11 голосов
/ 31 августа 2011

В 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
2 голосов
/ 30 мая 2017

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

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

1) Скопируйте данные с удаленного сервера на локальный компьютер (vps - это псевдоним вашего удаленного сервера, его можно заменить на root@1.2.3.4)

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
2 голосов
/ 25 мая 2017

Обратите внимание, что есть команда mysqldbcopy как часть утилит add on mysql .... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html

1 голос
/ 08 января 2018

Все предыдущие решения достигают некоторой точки, однако они просто не копируют все заново. Я создал функцию 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]));
        }
    }
}
0 голосов
/ 20 марта 2019

создание команд SQL для дублирования строк:

select @fromdb:="crm";
select @todb:="crmen";

SET group_concat_max_len=100000000;


SELECT  GROUP_CONCAT( concat("CREATE TABLE `",@todb,"`.`",table_name,"` LIKE `",@fromdb,"`.`",table_name,"`;\n",
"INSERT INTO `",@todb,"`.`",table_name,"` SELECT * FROM `",@fromdb,"`.`",table_name,"`;") 

SEPARATOR '\n\n')

as sqlstatement
 FROM information_schema.tables where table_schema=@fromdb and TABLE_TYPE='BASE TABLE';
0 голосов
/ 10 декабря 2017

Лучший способ клонировать таблицы базы данных без 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 ужасно медленная , если размер базы данных превышает 2 ГБ. И вы не можете клонировать таблицы InnoDB, просто копируя файлы БД (например, резервное копирование моментальных снимков).

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