mysqldumpを使用せずにデータベースをコピー/複製する


427

サーバーへのローカルアクセスなしで、MySQL db(コンテンツありとコンテンツなし)を使用せずに別のものに複製/クローンする方法はありますmysqldumpか?

現在MySQL 4.0を使用しています。


12
何が問題になっていmysqldumpますか?
Michael

48
これを行わないようにしてください:CREATE TABLE t2 SELECT * FROM t1;インデックス情報、auto_incrementなどの特別なものは失われます。このコピーテーブル用の多くのgoogleはこれを行うことにつながり、望ましくない結果になります。
ジョン・ハント

59
オフトピックの質問には、92の賛成票と37のお気に入りが追加されます。そのような話題外の質問に賛成です。古いガイドライン。
pal4life 2013

25
100%は、「閉ざされたトピック」が間違っていること、およびガイドラインを更新する必要があることに同意します。より寛大さが必要です-SOは間違った方向に向かっています。@willが完全にマークから外れていることは明らかであり、モデレーター権限を削除する必要があります。この1つの質問で十分です。
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 2012

42
端末の履歴にパスワードのプレーンテキストを保存したくない場合は、コマンドを分割する必要があり ますmysqldump -h [server] -u [user] -p db1 > db1mysql -h [server] -u [user] -p db2 < db1それ以外の場合は、少なくともputtyを使用しているときに、パスワードのプロンプトが混乱します。
kapex 2012年

5
ユーザー/ホスト/パスワードファイルを保存するように.my.cnfファイルを設定すると、mysqldumpとmysqlをbashから使用するのがはるかに簡単になります
ErichBSchulz '11

4
mysqldump -u root -p -v db1 | mysql -u root -p db22回パスに入る
hlcs

6
神様、誰かが「mysqldumpなしで」と言う質問がmysqldumpを使用する最初の応答として持っている理由を説明してくれませんか。のように、正しいものより6倍多い票?
c'mon

135

次のコマンドを実行すると、データのないテーブルを複製できます。

CREATE TABLE x LIKE y;

MySQL CREATE TABLEドキュメントを参照)

SHOW TABLES1つのデータベースから出力を取得し、スキーマを別のデータベースにコピーするスクリプトを作成できます。次のようなスキーマ+テーブル名を参照できるはずです。

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には、データの同期に役立つスクリプトがいくつかあります。速くはないかもしれませんが、おそらくロックせずにライブデータで同期スクリプトを実行できます。


1
これは重複テーブルの作業ですか?コマンドがCREATE TABLE
GusDeCooL


3
MyISAMデータベースのテーブルファイルを1回コピーしようとしましたが、新しいデータベースが破損しました。おそらく私の悪いですが、それは間違いなくいくつかの人が言うほど簡単な操作ではありません。
Johan Fredrik Varen 2013

2
これは素晴らしいトリックで、私はファンですが、重要な注意事項:これはMySQL Docsによる
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
ペリ

これは制約データやテーブルの他のプロパティもコピーしますか?
Lucas Moeskops、2011

1
彼は、元のすべてのプロパティを使用してCREATE TABLEを生成する「SHOW CREATE TABLE」ステートメントを使用しているため、そうです。
ダニタ

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
コードコマンダー

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 2017

このスクリプトはビューをカウントしません
sd1sd1 '28

4

mysqlユーティリティのアドオンの一部としてmysqldbcopyコマンドがあることに注意してください... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html


:しかし、それは、追加パッケージのインストールが必要ですapt install mysql-utilities
ジョエル・Gマシュー

2
しかし、それが不可能であるという制限はありませんでした。そして、それは一般的にインストールされるものです(しかし、あなたが言うようにオプションです)。 、など...
furicle

リンク以外の情報が含まれていなかったため、投稿はおそらく反対票を投じられました。答えはより包括的であるはずです。
ジョエルGマシュー2018

1

「ローカルアクセス」の意味がよくわかりません。しかし、そのソリューションでは、 ssh経由でサーバーにアクセスして、データベースが格納されているファイルコピーできる必要があります。

データベースが大きいため、mysqldumpを使用できません(7Go、mysqldumpが失敗)。

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 2018

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のみです。構造体をで高速に取得し、挿入ステートメントのみのクローンを作成するために使用できます。

なぜそれが実際の質問なのか?なぜなら mysqldumpsのアップロードが遅い醜いある DBが2GBを超えている場合。また、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.