Sin acceso local al servidor, ¿hay alguna forma de duplicar / clonar una base de datos MySQL (con contenido y sin contenido) en otra sin usar mysqldump
?
Actualmente estoy usando MySQL 4.0.
Puedo ver que dijiste que no querías usar mysqldump
, pero llegué a esta página mientras buscaba una solución similar y otros podrían encontrarla también. Con eso en mente, aquí hay una manera simple de duplicar una base de datos desde la línea de comandos de un servidor de Windows:
db2
es la base de datos de destino, donde db1
se copiará la base de datos de origen .mysqldump -h [server] -u [user] -p[password] db1 | mysql -h [server] -u [user] -p[password] db2
Nota: NO hay espacio entre -p
y[password]
mysqldump -h [server] -u [user] -p db1 > db1
, mysql -h [server] -u [user] -p db2 < db1
el mensaje de contraseña lo estropea, al menos para mí cuando usa masilla.
mysqldump -u root -p -v db1 | mysql -u root -p db2
y dos veces entrará pase
Puede duplicar una tabla sin datos ejecutando:
CREATE TABLE x LIKE y;
(Consulte los documentos de MySQL CREATE TABLE )
Podría escribir una secuencia de comandos que tome la salida SHOW TABLES
de una base de datos y copie el esquema en otra. Debería poder hacer referencia a nombres de esquema + tabla como:
CREATE TABLE x LIKE other_db.y;
En lo que respecta a los datos, también puede hacerlo en MySQL, pero no es necesariamente rápido. Después de crear las referencias, puede ejecutar lo siguiente para copiar los datos:
INSERT INTO x SELECT * FROM other_db.y;
Si está utilizando MyISAM, es mejor que copie los archivos de la tabla; Será mucho más rápido. Debería poder hacer lo mismo si está utilizando INNODB con espacios de tabla por tabla .
Si terminas haciendo un INSERT INTO SELECT
, ¡asegúrate de desactivar temporalmente los índices con ALTER TABLE x DISABLE KEYS
!
EDITAR Maatkit también tiene algunos scripts que pueden ser útiles para sincronizar datos. Puede que no sea más rápido, pero probablemente podría ejecutar sus scripts de sincronización en datos en vivo sin mucho bloqueo.
Si está utilizando Linux, puede usar este script bash: (tal vez necesite una limpieza adicional del código pero funciona ... y es mucho más rápido 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}
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
echo "set foreign_key_checks = 0; $fCreateTable ; $fInsertData ; set foreign_key_checks = 1;" | mysql $DBCONN $DBNAME
SHOW TABLES
línea SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'
y agregando | cut -f 1
. La línea completa debería verse más o menos así, pero reemplace las líneas de retroceso dobles con líneas de fondo simples: for TABLE in ``echo "SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE'" | mysql $DBCONN $DBSNAME | tail -n +2 | cut -f 1``; do
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
Tenga en cuenta que hay un comando mysqldbcopy como parte del complemento de las utilidades mysql ... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html
apt install mysql-utilities
Realmente no sé qué quieres decir con "acceso local". Pero para esa solución, debe poder acceder a través del servidor ssh para copiar los archivos donde se almacena la base de datos .
No puedo usar mysqldump, porque mi base de datos es grande (7Go, mysqldump falla) Si la versión de la base de datos 2 mysql es demasiado diferente, puede que no funcione, puede verificar su versión de mysql usando mysql -V.
1) Copie los datos de su servidor remoto a su computadora local (vps es el alias de su servidor remoto, puede ser reemplazado por 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) Importe los datos copiados en su computadora local
/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
Si tiene una versión diferente, es posible que deba ejecutar
/etc/init.d/mysql stop
mysql_upgrade -u root -pPASSWORD --force #that step took almost 1hrs
/etc/init.d/mysql start
Todas las soluciones anteriores llegan al punto un poco, sin embargo, simplemente no copian todo. Creé una función PHP (aunque algo larga) que copia todo, incluyendo tablas, claves foráneas, datos, vistas, procedimientos, funciones, disparadores y eventos. Aquí está el código:
/* 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
en términos de eficiencia.
En realidad, quería lograr exactamente eso en PHP, pero ninguna de las respuestas aquí fue muy útil, así que aquí está mi solución, bastante sencilla, usando 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;
La mejor manera de clonar tablas de bases de datos sin mysqldump:
Crear consultas de clonación con consulta:
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';
¡Ejecuta esa salida!
Pero tenga en cuenta que la secuencia de comandos anterior solo clona tablas rápidas , no vistas, disparadores y funciones de usuario: puede obtener una estructura rápida mysqldump --no-data --triggers -uroot -ppassword
y luego usar para clonar solo insertar instrucciones.
¿Por qué es una pregunta real? Debido a que la carga de mysqldumps es muy lenta si la DB supera los 2 Gb. Y no puede clonar tablas de InnoDB simplemente copiando archivos DB (como la copia de seguridad de instantáneas).
un SQL que muestra comandos SQL, debe ejecutarse para duplicar una base de datos de una base de datos a otra. para cada tabla se crea una declaración de tabla y una declaración de inserción. se supone que ambas bases de datos están en el mismo servidor:
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 no es una mala solución. La forma más simple de duplicar la base de datos:
mysqldump -uusername -ppass dbname1 | mysql -uusername -ppass dbname2
Además, puede cambiar el motor de almacenamiento de esta manera:
mysqldump -uusername -ppass dbname1 | sed 's/InnoDB/RocksDB/' | mysql -uusername -ppass dbname2
mysqldump
?CREATE TABLE t2 SELECT * FROM t1;
ya que perderá su información de índice, cualquier cosa especial como auto_increment, etc. muchos de los google para este tipo de tabla de copia lo llevarán a hacer esto y tendrá resultados no deseados .