mysqldump를 사용하지 않고 데이터베이스 복사 / 복제


427

서버에 로컬로 액세스하지 않으면 MySQL 데이터베이스 (콘텐츠가 있고 내용이없는)를 사용하지 않고 다른 데이터베이스로 복제 / 복제 할 수있는 방법이 mysqldump있습니까?

현재 MySQL 4.0을 사용하고 있습니다.


12
무슨 일이야 mysqldump?
Michael Mior 2016 년

48
당신이 있는지 확인 하지 않습니다 이 작업을 수행 : CREATE TABLE t2 SELECT * FROM t1;당신이이 일에 당신을 이끌 것입니다 색인 정보, AUTO_INCREMENT 등 많은 구글의 종류의 일이 복사 테이블과 같은 특별한 물건을 잃게됩니다로서 그것은 유엔 원하는 결과를해야합니다 .
John Hunt

59
주제를 벗어난 질문은 92 개의 공감대와 37 개의 즐겨 찾기를 얻습니다. 그런 주제를 벗어난 질문에 대해서는 거절하십시오. 오래된 지침.
pal4life

25
100 %는 "주제 마감"이 잘못되었고 길드 라인을 업데이트해야한다는 점에 동의합니다. 더 많은 관대함이 필요합니다.-SO가 잘못된 방향으로 가고 있습니다. @will이 완전히 표시되지 않았으며 중재자 권한을 제거해야한다는 것이 분명합니다.이 단일 질문으로 충분합니다.
stolsvik

10
주제를 벗어난 것이 100 % 잘못되었으므로 마감되었습니다. 이것은 내가 가진 정확한 질문이며, 단순한 의견과 관련이없는 잘 정의 된 기술 답변이 있습니다. 중재자가 "최고"와 같은 단어를 찾아서 닫을 질문을 찾은 것 같습니다.
Sam Goldberg

답변:


686

님이 사용하고 싶지 않다고 말 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]


108
mysqldump에 대한 사례 는 데이터를 쿼리로 직렬화하고 쿼리를 프로세스 외부로 전송하고 tty를 통해 동일한 프로세스 로 다시 전송하고 쿼리를 재분석하고 명령문으로 실행 하는 더 빠른 방법이 필요하다는 것 입니다. 그것은 비효율적이고 불필요하게 들립니다 . 우리는 MySQL 마스터 간의 교차 또는 스토리지 엔진 변경에 대해 이야기하지 않습니다. 효율적인 프로세스 내 이진 전송이 없다는 것은 충격입니다.
Toddius Zho

42
: 당신이 당신의 터미널 역사에 암호 일반 텍스트를 저장하지 않으려면, 당신은 명령을 분할해야 mysqldump -h [server] -u [user] -p db1 > db1, mysql -h [server] -u [user] -p db2 < db1 나를 위해 적어도 퍼티를 사용하는 경우, 그렇지 않은 경우 암호 프롬프트 놨 그것을.
kapex

5
.my.cnf 파일을 설정하여 사용자 / 호스트 / 암호 파일을 저장하면 bash에서 mysqldump 및 mysql을 사용하는 것이 훨씬 간단 해집니다
ErichBSchulz

4
mysqldump -u root -p -v db1 | mysql -u root -p db2그리고 두 번 패스를 입력
hlcs 12

6
신, 누군가 "mysqldump없이"라는 질문에 mysqldump를 사용하는 첫 번째 응답이있는 이유를 설명해 주시겠습니까? 올바른 투표보다 6 배 더 많은 표를 얻 습니까? c'mon, SO ...
igorsantos07

135

다음을 실행하여 데이터없이 테이블을 복제 할 수 있습니다.

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!

편집 Maatkit 에는 데이터 동기화에 도움이되는 스크립트도 있습니다. 더 빠르지는 않지만 많은 잠금없이 라이브 데이터에서 동기화 스크립트를 실행할 수 있습니다.


1
중복 테이블에 대한 작업입니까? 명령이 CREATE TABLE
GusDeCooL

4
할 수 있습니다 CREATE TABLE ... SELECT.
eggyal

3
MyISAM 데이터베이스의 테이블 파일을 한 번 복사하려고 시도했지만 새 데이터베이스가 손상되었습니다. 아마 내 나쁜 일이지만, 일부 사람들이 말한 것처럼 확실히 사소한 작업은 아닙니다.
Johan Fredrik Varen

2
이 멋진 트릭 내가 팬입니다 만, 중요한 참고 : 이 모든 외래 키 제약 이월하지 않는 당 (복사되는 스키마에 대한 외부에도 사람) MySQL의 문서
abigperson

59

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

7
위의 스크립트를 InnoDB 테이블과 함께 사용하고 외래 키가있는 경우 마지막 줄을 다음과 같이 변경하십시오.echo "set foreign_key_checks = 0; $fCreateTable ; $fInsertData ; set foreign_key_checks = 1;" | mysql $DBCONN $DBNAME
pegli

제약 조건 데이터와 테이블의 다른 속성도 복사합니까?
Lucas Moeskops

1
그는 원본의 모든 속성을 가진 CREATE TABLE을 생성하는 "SHOW CREATE TABLE"문을 사용하기 때문에 그렇게 보인다.
Danita

1
@zirael에서 설명한 문제가 발생하면 스크립트가 뷰를 복사하지 못했기 때문일 수 있습니다. SHOW TABLES행을 변경 SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'하고을 추가 하여 사본에서보기를 무시할 수 있습니다 | cut -f 1. 완전한 라인은 다음과 같아야하지만 이중 백틱을 단일 백틱으로 대체해야합니다. for TABLE in ``echo "SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'" | mysql $DBCONN $DBSNAME | tail -n +2 | cut -f 1``; do
Code Commander

1
@jozjan이이 스크립트를 정리하고 GIST에서이 버전을 만들기 위해 외래 및 기타 키에 대한 의견을 적용했습니다. gist.github.com/christopher-hopper/8431737
Christopher

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

Windows 시스템에서 작업중인 경우 그런 다음 명령을 실행하는 긴 방법을 찾는 대신 친절하게 사용하십시오.
Parixit

이 스크립트는 조회수를 계산하지 않습니다
sd1sd1

4

mysql 유틸리티에 대한 추가의 일부로 mysqldbcopy 명령이 있습니다 .... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html


그러나 추가 패키지를 설치해야합니다.apt install mysql-utilities
Joel G Mathew

2
그러나 불가능하다고 말하는 제한은 없었습니다 .... 일반적으로 설치되는 것입니다 (그러나 선택 사항입니다) 설치되지 않은 경우 많은 사람들이 60 줄 Bash 스크립트를 설정하고 실행하는 것보다 해당 패키지를 설치하는 것이 더 쉽다는 것을 알게 될 것입니다 등 ...
furicle

링크 이외의 다른 정보를 포함하지 않았기 때문에 게시물에 투표가 거부되었을 수 있습니다. 답변은보다 포괄적이어야합니다.
Joel G Mathew

1

"로컬 액세스"가 무슨 뜻인지 잘 모르겠습니다. 그러나 해당 솔루션의 경우 ssh를 통해 서버에 액세스하여 데이터베이스가 저장된 파일복사 할 수 있어야합니다 .

내 데이터베이스가 크기 때문에 (7Go, mysqldump 실패) mysqldump를 사용할 수 없습니다. 2 mysql 데이터베이스의 버전이 너무 다르면 작동하지 않을 수 있습니다. mysql -V를 사용하여 mysql 버전을 확인할 수 있습니다.

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

이것이 가장 효율적인 방법이지만 "서버에 대한 로컬 액세스가 없으면"시스템에 액세스 할 수 없음을 의미합니다. 아마 공유 호스팅? 따라서 이것은 답이 아닙니다.
Valerio Bozz

1

이전의 모든 솔루션은 요점에 조금만 도달하지만 모든 것을 복사하지는 않습니다. 테이블, 외래 키, 데이터, 뷰, 프로 시저, 함수, 트리거 및 이벤트를 포함한 모든 것을 복사하는 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]));
        }
    }
}

질문은 "mysqldump를 사용하지 마십시오"가 아니라 "mysqldump보다 더 나은 접근 방법을 사용하기"때문입니다. 이것은 mysqldump효율성 측면에서 더 나쁩니다 .
Valerio Bozz

1

실제로 PHP에서 정확히 달성하고 싶었지만 여기에 대한 답변은별로 도움이되지 않았으므로 여기에는 MySQLi를 사용하는 매우 간단한 솔루션이 있습니다.

// Database variables

$DB_HOST = 'localhost';
$DB_USER = 'root';
$DB_PASS = '1234';

$DB_SRC = 'existing_db';
$DB_DST = 'newly_created_db';



// MYSQL Connect

$mysqli = new mysqli( $DB_HOST, $DB_USER, $DB_PASS ) or die( $mysqli->error );



// Create destination database

$mysqli->query( "CREATE DATABASE $DB_DST" ) or die( $mysqli->error );



// Iterate through tables of source database

$tables = $mysqli->query( "SHOW TABLES FROM $DB_SRC" ) or die( $mysqli->error );

while( $table = $tables->fetch_array() ): $TABLE = $table[0];


    // Copy table and contents in destination database

    $mysqli->query( "CREATE TABLE $DB_DST.$TABLE LIKE $DB_SRC.$TABLE" ) or die( $mysqli->error );
    $mysqli->query( "INSERT INTO $DB_DST.$TABLE SELECT * FROM $DB_SRC.$TABLE" ) or die( $mysqli->error );


endwhile;

tihis가 1 : 1 복제본을 만드는지 확실하지 않지만 간단한 데이터베이스로 충분할 것 같습니다.
beppe9000

개발 서버에서 빠른 WordPress 설치를 만드는 데 사용하고 있습니다. 이 부분은 다른 루틴과 짝을 이루어 소스 설치를 새 프로젝트로 복제하고 조정합니다. 이를 위해서는 잘 작동하지만… 빈 워드 프레스 데이터베이스는 그다지 복잡하지 않으므로 더 광범위한 사용 사례에 대한 진술을 할 수 없습니다
GDY

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가져온 다음 insert 문만 복제하는 데 사용할 수 있습니다.

왜 실제 질문입니까? 때문에 mysqldumps의 업로드 못생긴 느린 DB는 기가 바이트를 초과합니다. 그리고 스냅 샷 백업과 같은 DB 파일을 복사하는 것만으로 InnoDB 테이블을 복제 할 수 없습니다.


0

SQL 명령을 표시하는 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';

-1

Mysqldump는 나쁜 해결책이 아닙니다. 데이터베이스를 복제하는 가장 간단한 방법 :

mysqldump -uusername -ppass dbname1 | mysql -uusername -ppass dbname2

또한 다음과 같은 방법으로 스토리지 엔진을 변경할 수 있습니다.

mysqldump -uusername -ppass dbname1 | sed 's/InnoDB/RocksDB/' | mysql -uusername -ppass dbname2

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.