Copy/duplicate database without using mysqldump

Mysql

Mysql Problem Overview


Without local access to the server, is there any way to duplicate/clone a MySQL db (with content and without content) into another without using mysqldump?

I am currently using MySQL 4.0.

Mysql Solutions


Solution 1 - Mysql

I can see you said you didn't want to use mysqldump, but I reached this page while looking for a similar solution and others might find it as well. With that in mind, here is a simple way to duplicate a database from the command line of a windows server:

  1. Create the target database using MySQLAdmin or your preferred method. In this example, db2 is the target database, where the source database db1 will be copied.
  2. Execute the following statement on a command line:

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

Note: There is NO space between -p and [password]

Solution 2 - Mysql

You can duplicate a table without data by running:

CREATE TABLE x LIKE y;

(See the MySQL CREATE TABLE Docs)

You could write a script that takes the output from SHOW TABLES from one database and copies the schema to another. You should be able to reference schema+table names like:

CREATE TABLE x LIKE other_db.y;

As far as the data goes, you can also do it in MySQL, but it's not necessarily fast. After you've created the references, you can run the following to copy the data:

INSERT INTO x SELECT * FROM other_db.y;

If you're using MyISAM, you're better off to copy the table files; it'll be much faster. You should be able to do the same if you're using INNODB with per table table spaces.

If you do end up doing an INSERT INTO SELECT, be sure to temporarily turn off indexes with ALTER TABLE x DISABLE KEYS!

EDIT Maatkit also has some scripts that may be helpful for syncing data. It may not be faster, but you could probably run their syncing scripts on live data without much locking.

Solution 3 - Mysql

If you are using Linux, you can use this bash script: (it perhaps needs some additional code cleaning but it works ... and it's much faster then 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

Solution 4 - Mysql

In 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

Solution 5 - Mysql

Note there is a mysqldbcopy command as part of the add on mysql utilities.... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html

Solution 6 - Mysql

All of the prior solutions get at the point a little, however, they just don't copy everything over. I created a PHP function (albeit somewhat lengthy) that copies everything including tables, foreign keys, data, views, procedures, functions, triggers, and events. Here is the code:

/* 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]));
		}
	}
}

Solution 7 - Mysql

Actually i wanted to achieve exactly that in PHP but none of the answers here were very helpful so here's my – pretty straightforward – solution using 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;

Solution 8 - Mysql

I don't really know what you mean by "local access". But for that solution you need to be able to access over ssh the server to copy the files where is database is stored.

I cannot use mysqldump, because my database is big (7Go, mysqldump fail) If the version of the 2 mysql database is too different it might not work, you can check your mysql version using mysql -V.

  1. Copy the data from your remote server to your local computer (vps is the alias to your remote server, can be replaced by [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. Import the data copied on your local computer

    /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

If you have a different version, you may need to run

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


Solution 9 - Mysql

The best way to clone database tables without mysqldump:

  1. Create a new database.

  2. Create clone-queries with query:

     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. Run that output!

But note, script above just fast clone tables - not views, triggers and user-functions: you can fast get structure by mysqldump --no-data --triggers -uroot -ppassword , and then use to clone only insert statement .

Why it is actual question? Because uploading of mysqldumps is ugly slow if DB is over 2Gb. And you can't clone InnoDB tables just by copying DB files (like snapshot backuping).

Solution 10 - Mysql

an SQL that shows SQL commands, need to run to duplicate a database from one database to another. for each table there is create a table statement and an insert statement. it assumes both databases are on the same server:

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';


 
 

Solution 11 - Mysql

Mysqldump isn't bad solution. Simplest way to duplicate database:

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

Also, you can change storage engine by this way:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjhornnesView Question on Stackoverflow
Solution 1 - MysqlRafeView Answer on Stackoverflow
Solution 2 - MysqlGary RichardsonView Answer on Stackoverflow
Solution 3 - MysqljozjanView Answer on Stackoverflow
Solution 4 - Mysqlmr_appView Answer on Stackoverflow
Solution 5 - MysqlfuricleView Answer on Stackoverflow
Solution 6 - MysqlDustinView Answer on Stackoverflow
Solution 7 - MysqlGDYView Answer on Stackoverflow
Solution 8 - MysqlRemy MelletView Answer on Stackoverflow
Solution 9 - MysqlAlexander GoncharovView Answer on Stackoverflow
Solution 10 - MysqlShimon DoodkinView Answer on Stackoverflow
Solution 11 - MysqlAndy AlView Answer on Stackoverflow