Copiez / dupliquez la base de données sans utiliser mysqldump
427
Sans accès local au serveur, existe-t-il un moyen de dupliquer / cloner une base de données MySQL (avec contenu et sans contenu) dans une autre sans utiliser mysqldump?
Assurez-vous que vous ne le faites pas : CREATE TABLE t2 SELECT * FROM t1;comme vous perdrez vos informations d'index, tout élément spécial comme auto_increment, etc. .
John Hunt du
59
Une question hors sujet obtient 92 votes positifs et 37 favoris. Bravo pour une telle question hors sujet. Lignes directrices obsolètes.
pal4life
25
100% sont d'accord pour dire que le "sujet fermé" est faux et que les lignes de guilde devraient être mises à jour - plus de clémence est nécessaire - SO se dirige dans la mauvaise direction. Il est évident que @will est complètement hors de propos et que ses privilèges de modérateur devraient être supprimés - cette seule question est une preuve suffisante.
stolsvik
10
Fermé car hors sujet est 100% faux. Telle est la question exacte que j'ai, et elle a une réponse technique bien définie qui ne se rapporte pas à une simple opinion. Je pense que le modérateur doit avoir fait une telle recherche de mots comme "meilleur" pour trouver des questions à fermer.
Sam Goldberg
Réponses:
686
Je peux voir que vous avez dit que vous ne vouliez pas l'utiliser mysqldump, mais j'ai atteint cette page en recherchant une solution similaire et d'autres pourraient également la trouver. Dans cet esprit, voici un moyen simple de dupliquer une base de données à partir de la ligne de commande d'un serveur Windows:
Créez la base de données cible à l'aide de MySQLAdmin ou de votre méthode préférée. Dans cet exemple, db2c'est la base de données cible, où la base de données source db1sera copiée.
Exécutez l'instruction suivante sur une ligne de commande:
L'argument contre mysqldump est qu'il doit y avoir un moyen plus rapide que de sérialiser les données en requêtes, de transmettre les requêtes en dehors du processus et à travers le tty de nouveau dans le même processus exact , de ré-analyser les requêtes et de les exécuter en tant qu'instructions. Cela semble horriblement inefficace et inutile . Nous ne parlons pas de passer entre les maîtres MySQL ou de changer les moteurs de stockage. C'est choquant qu'il n'y ait pas de transfert binaire intraprocessus efficace.
Toddius Zho
42
Si vous ne souhaitez pas enregistrer le texte en clair mot de passe dans l' historique de vos terminaux, vous devez diviser la commande suivante : mysqldump -h [server] -u [user] -p db1 > db1, mysql -h [server] -u [user] -p db2 < db1 Sinon le mot de passe mess rapides vers le haut, au moins pour moi lors de l' utilisation du mastic.
kapex
5
utiliser mysqldump et mysql de bash devient beaucoup plus simple si vous configurez votre fichier .my.cnf pour stocker vos fichiers utilisateur / hôte / mot de passe
ErichBSchulz
4
mysqldump -u root -p -v db1 | mysql -u root -p db2et deux fois entrer la passe
hlcs
6
dieu, quelqu'un pourrait-il expliquer pourquoi une question indiquant "sans mysqldump" a comme première réponse une question qui utilise mysqldump? avec comme, 6x plus de votes que le bon ? allez, SO ...
igorsantos07
135
Vous pouvez dupliquer une table sans données en exécutant:
Vous pouvez écrire un script qui prend la sortie SHOW TABLESd'une base de données et copie le schéma dans une autre. Vous devriez pouvoir référencer les noms de schéma + table comme:
CREATETABLE x LIKE other_db.y;
En ce qui concerne les données, vous pouvez également le faire dans MySQL, mais ce n'est pas nécessairement rapide. Après avoir créé les références, vous pouvez exécuter ce qui suit pour copier les données:
INSERTINTO x SELECT*FROM other_db.y;
Si vous utilisez MyISAM, vous feriez mieux de copier les fichiers de table; ce sera beaucoup plus rapide. Vous devriez pouvoir faire de même si vous utilisez INNODB avec des espaces table par table .
Si vous finissez par faire un INSERT INTO SELECT, assurez-vous de désactiver temporairement les index avec ALTER TABLE x DISABLE KEYS!
EDIT Maatkit possède également certains scripts qui peuvent être utiles pour la synchronisation des données. Ce n'est peut-être pas plus rapide, mais vous pourriez probablement exécuter leurs scripts de synchronisation sur des données en direct sans trop de verrouillage.
J'ai essayé de copier une fois les fichiers de table d'une base de données MyISAM, mais cela a juste corrompu la nouvelle base de données. Probablement ma mauvaise, mais ce n'est certainement pas une opération aussi triviale que certains le disent.
Johan Fredrik Varen
2
C'est une bonne astuce et je suis fan, mais une note importante: cela ne
recouvre
59
Si vous utilisez Linux, vous pouvez utiliser ce script bash: (il a peut-être besoin d'un nettoyage de code supplémentaire mais cela fonctionne ... et c'est beaucoup plus rapide que 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}forTABLEin`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
Si vous utilisez le script ci-dessus avec des tables InnoDB et avez des clés étrangères, changez la dernière ligne comme suit:echo "set foreign_key_checks = 0; $fCreateTable ; $fInsertData ; set foreign_key_checks = 1;" | mysql $DBCONN $DBNAME
pegli
Est-ce que cela copie également les données de contrainte et d'autres propriétés des tables?
Lucas Moeskops
1
Il semble que oui, car il utilise une instruction "SHOW CREATE TABLE" qui génère une CREATE TABLE avec toutes les propriétés de l'original.
Danita
1
Si vous rencontrez le problème décrit par @zirael, c'est probablement parce que le script ne parvient pas à copier les vues. Vous pouvez ignorer les vues de la copie en modifiant la SHOW TABLESligne SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'et en ajoutant | cut -f 1. La ligne complète devrait ressembler à ceci mais remplacer les doubles backticks par des simples backticks: 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
J'ai nettoyé ce script par @jozjan et appliqué certains des commentaires concernant les clés étrangères et autres pour créer cette version sur GIST gist.github.com/christopher-hopper/8431737
Christopher
11
En 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
Mais cela nécessite l'installation d'un package supplémentaire:apt install mysql-utilities
Joel G Mathew
2
Mais il n'y avait aucune restriction disant que ce n'était pas possible .... et c'est une chose couramment installée (mais facultative comme vous le dites) Si elle n'est pas installée, beaucoup trouveraient l'installation de ce paquet plus facile que la configuration et l'exécution d'un script Bash de 60 lignes , etc ....
furicule
Votre message a probablement été rejeté parce que vous n'avez inclus aucune autre information qu'un lien. Les réponses sont censées être plus complètes.
Joel G Mathew
1
Je ne sais pas vraiment ce que vous entendez par "accès local". Mais pour cette solution, vous devez pouvoir accéder via ssh au serveur pour copier les fichiers où se trouve la base de données .
Je ne peux pas utiliser mysqldump, car ma base de données est grande (7Go, mysqldump échoue) Si la version de la base de données 2 mysql est trop différente, cela pourrait ne pas fonctionner, vous pouvez vérifier votre version mysql en utilisant mysql -V.
1) Copiez les données de votre serveur distant sur votre ordinateur local (vps est l'alias de votre serveur distant, peut être remplacé par [email protected])
C'est le moyen le plus efficace de le faire mais je pense que "sans accès local au serveur" signifie que nous ne pouvons pas accéder au système. Probablement un hébergement mutualisé? Ce n'est donc pas la réponse.
Valerio Bozz du
1
Toutes les solutions antérieures arrivent un peu au point, cependant, elles ne copient pas tout. J'ai créé une fonction PHP (quoique quelque peu longue) qui copie tout, y compris les tables, les clés étrangères, les données, les vues, les procédures, les fonctions, les déclencheurs et les événements. Voici le 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 schemaif 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 ifany 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 tabletoaddforeignkeyandinsert 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 allforeign keys for a particular tablein 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 ifanyforeign keys were returned and recreates them in the new schema// Note:ONUPDATEandONDELETE 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 ifany views were returned and recreates them in the new schemaif(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 ifany triggers were returned and recreates them in the new schemaif(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 ifany procedures were returned and recreates them in the new schemaif(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 ifany functions were returned and recreates them in the new schemaif(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 ifany events were returned and recreates them in the new schemaif(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]));}}}
Voté parce que la question n'est pas "ne pas utiliser mysqldump" mais "utiliser une meilleure approche que mysqldump". C'est encore pire mysqldumpen termes d'efficacité.
Valerio Bozz
1
En fait, je voulais atteindre exactement cela en PHP, mais aucune des réponses ici n'était très utile, alors voici ma - assez simple - solution utilisant 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 tableand 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;
Je ne suis pas sûr que cela fasse un clone 1: 1 mais il semble que des bases de données simples pourraient être suffisantes.
beppe9000
Je l'utilise pour créer des installations WordPress rapides sur mon serveur de développement. Cette partie associée à d'autres routines dupliquent et ajustent une installation source dans un nouveau projet. Pour cela, cela fonctionne très bien… mais une base de données wordpress vierge n'est pas très complexe, donc je ne peux pas faire de déclaration pour des cas d'utilisation plus étendus
GDY
0
La meilleure façon de cloner des tables de base de données sans mysqldump:
Créez une nouvelle base de données.
Créez des requêtes de clonage avec une requête:
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';
Exécutez cette sortie!
Mais notez, le script au-dessus des tables de clonage rapide seulement - pas les vues, les déclencheurs et les fonctions utilisateur: vous pouvez rapidement obtenir la structure par mysqldump --no-data --triggers -uroot -ppassword, puis utiliser pour cloner uniquement l'insertion d'une instruction.
Pourquoi c'est une question réelle? Parce que le téléchargement de mysqldumps est très lent si DB dépasse 2 Go. Et vous ne pouvez pas cloner des tables InnoDB simplement en copiant des fichiers DB (comme la sauvegarde d'instantanés).
un SQL qui affiche des commandes SQL, doit être exécuté pour dupliquer une base de données d'une base de données à une autre. pour chaque table, il existe une instruction de table et une instruction d'insertion. il suppose que les deux bases de données sont sur le même serveur:
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';
mysqldump
?CREATE TABLE t2 SELECT * FROM t1;
comme vous perdrez vos informations d'index, tout élément spécial comme auto_increment, etc. .Réponses:
Je peux voir que vous avez dit que vous ne vouliez pas l'utiliser
mysqldump
, mais j'ai atteint cette page en recherchant une solution similaire et d'autres pourraient également la trouver. Dans cet esprit, voici un moyen simple de dupliquer une base de données à partir de la ligne de commande d'un serveur Windows:db2
c'est la base de données cible, où la base de données sourcedb1
sera copiée.mysqldump -h [server] -u [user] -p[password] db1 | mysql -h [server] -u [user] -p[password] db2
Remarque: il n'y a PAS d'espace entre
-p
et[password]
la source
mysqldump -h [server] -u [user] -p db1 > db1
,mysql -h [server] -u [user] -p db2 < db1
Sinon le mot de passe mess rapides vers le haut, au moins pour moi lors de l' utilisation du mastic.mysqldump -u root -p -v db1 | mysql -u root -p db2
et deux fois entrer la passeVous pouvez dupliquer une table sans données en exécutant:
(Voir les documents MySQL CREATE TABLE )
Vous pouvez écrire un script qui prend la sortie
SHOW TABLES
d'une base de données et copie le schéma dans une autre. Vous devriez pouvoir référencer les noms de schéma + table comme:En ce qui concerne les données, vous pouvez également le faire dans MySQL, mais ce n'est pas nécessairement rapide. Après avoir créé les références, vous pouvez exécuter ce qui suit pour copier les données:
Si vous utilisez MyISAM, vous feriez mieux de copier les fichiers de table; ce sera beaucoup plus rapide. Vous devriez pouvoir faire de même si vous utilisez INNODB avec des espaces table par table .
Si vous finissez par faire un
INSERT INTO SELECT
, assurez-vous de désactiver temporairement les index avecALTER TABLE x DISABLE KEYS
!EDIT Maatkit possède également certains scripts qui peuvent être utiles pour la synchronisation des données. Ce n'est peut-être pas plus rapide, mais vous pourriez probablement exécuter leurs scripts de synchronisation sur des données en direct sans trop de verrouillage.
la source
CREATE TABLE ... SELECT
.Si vous utilisez Linux, vous pouvez utiliser ce script bash: (il a peut-être besoin d'un nettoyage de code supplémentaire mais cela fonctionne ... et c'est beaucoup plus rapide que mysqldump | mysql)
la source
echo "set foreign_key_checks = 0; $fCreateTable ; $fInsertData ; set foreign_key_checks = 1;" | mysql $DBCONN $DBNAME
SHOW TABLES
ligneSHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'
et en ajoutant| cut -f 1
. La ligne complète devrait ressembler à ceci mais remplacer les doubles backticks par des simples backticks:for TABLE in ``echo "SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'" | mysql $DBCONN $DBSNAME | tail -n +2 | cut -f 1``; do
En PHP:
la source
Notez qu'il existe une commande mysqldbcopy dans le cadre de l'utilitaire add on mysql .... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html
la source
apt install mysql-utilities
Je ne sais pas vraiment ce que vous entendez par "accès local". Mais pour cette solution, vous devez pouvoir accéder via ssh au serveur pour copier les fichiers où se trouve la base de données .
Je ne peux pas utiliser mysqldump, car ma base de données est grande (7Go, mysqldump échoue) Si la version de la base de données 2 mysql est trop différente, cela pourrait ne pas fonctionner, vous pouvez vérifier votre version mysql en utilisant mysql -V.
1) Copiez les données de votre serveur distant sur votre ordinateur local (vps est l'alias de votre serveur distant, peut être remplacé par [email protected])
2) Importez les données copiées sur votre ordinateur local
Si vous avez une version différente, vous devrez peut-être exécuter
la source
Toutes les solutions antérieures arrivent un peu au point, cependant, elles ne copient pas tout. J'ai créé une fonction PHP (quoique quelque peu longue) qui copie tout, y compris les tables, les clés étrangères, les données, les vues, les procédures, les fonctions, les déclencheurs et les événements. Voici le code:
la source
mysqldump
en termes d'efficacité.En fait, je voulais atteindre exactement cela en PHP, mais aucune des réponses ici n'était très utile, alors voici ma - assez simple - solution utilisant MySQLi:
la source
La meilleure façon de cloner des tables de base de données sans mysqldump:
Créez des requêtes de clonage avec une requête:
Exécutez cette sortie!
Mais notez, le script au-dessus des tables de clonage rapide seulement - pas les vues, les déclencheurs et les fonctions utilisateur: vous pouvez rapidement obtenir la structure par
mysqldump --no-data --triggers -uroot -ppassword
, puis utiliser pour cloner uniquement l'insertion d'une instruction.Pourquoi c'est une question réelle? Parce que le téléchargement de mysqldumps est très lent si DB dépasse 2 Go. Et vous ne pouvez pas cloner des tables InnoDB simplement en copiant des fichiers DB (comme la sauvegarde d'instantanés).
la source
un SQL qui affiche des commandes SQL, doit être exécuté pour dupliquer une base de données d'une base de données à une autre. pour chaque table, il existe une instruction de table et une instruction d'insertion. il suppose que les deux bases de données sont sur le même serveur:
la source
Mysqldump n'est pas une mauvaise solution. Manière la plus simple de dupliquer la base de données:
mysqldump -uusername -ppass dbname1 | mysql -uusername -ppass dbname2
Vous pouvez également modifier le moteur de stockage de cette façon:
mysqldump -uusername -ppass dbname1 | sed 's/InnoDB/RocksDB/' | mysql -uusername -ppass dbname2
la source