Sin acceso local al servidor, ¿hay alguna manera de duplicar/clonar un MySQL db (con contenido y sin contenido) en otro sin usar mysqldump
?Copiar/duplicar base de datos sin usar mysqldump
Actualmente estoy usando MySQL 4.0.
Sin acceso local al servidor, ¿hay alguna manera de duplicar/clonar un MySQL db (con contenido y sin contenido) en otro sin usar mysqldump
?Copiar/duplicar base de datos sin usar mysqldump
Actualmente estoy usando MySQL 4.0.
Puede duplicar una tabla sin datos ejecutando:
CREATE TABLE x LIKE y;
(Ver las MySQL CREATE TABLE Docs)
Se puede escribir un script que toma la salida de SHOW TABLES
de una base de datos y copia el esquema de otro. Usted debe ser capaz de hacer referencia a nombres de esquema + mesa como:
CREATE TABLE x LIKE other_db.y;
Por lo que van 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á usando MyISAM, que es mejor para copiar los archivos de la tabla; será mucho más rápido. Debería poder hacer lo mismo si está utilizando INNODB con per table table spaces.
Si terminas haciendo un INSERT INTO SELECT
, asegúrate de temporalmente turn off indexes con ALTER TABLE x DISABLE KEYS
!
EDITMaatkit también tiene algunos scripts que pueden ser útiles para sincronizar datos. Puede que no sea más rápido, pero probablemente puedas ejecutar sus scripts de sincronización en datos en vivo sin demasiado bloqueo.
es este trabajo para la tabla duplicada? dado que veo el comando es CREATE TABLE – GusDeCooL
Puede hacer ['CREATE TABLE ... SELECT'] (http://dev.mysql.com/doc/refman/4.1/en/create-table-select.html). – eggyal
Intenté copiar los archivos de tabla de una base de datos MyISAM una vez, pero eso corrompió la nueva base de datos. Probablemente sea malo, pero definitivamente no es una operación tan trivial como algunos dicen que es. –
Si está utilizando Linux, puede utilizar este script bash: (quizás necesita un poco de código adicional limpieza 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
¿Esto también copia los datos de restricción y otras propiedades de las tablas? –
Parece que sí, porque usa una instrucción "SHOW CREATE TABLE" que genera una CREATE TABLE con todas las propiedades del original. – Danita
¿Soy yo o no funciona? Creó solo unas pocas tablas y arrojó esto: Copiando la base de datos (...) ERROR 1064 (42000) en la línea 1: Tiene un error en su sintaxis SQL; revise el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de '-modelowanie-copy' en la línea 1 ERROR 1064 (42000) en la línea 1: tiene un error en su sintaxis SQL; revise el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de '-modelowanie-copy' en la línea 1 – zirael
que pueda veo 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 esto en mente, aquí hay una manera simple de duplicar una base de datos desde la línea de comando de un servidor de Windows:
db2
es la base de datos de destino, donde se copiará la base de datos de origen db1
.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: Tengo error: 1449: El usuario especificado como definidor ('root'@'127.0.0.1') no existe cuando se usa LOCK TABLES – Tjorriemorrie
/¿cuál sería en realidad una buena razón para NO usar mysqldump? –
El caso en contra de ** mysqldump ** es que tiene que haber una manera más rápida que serializar los datos en las consultas, transmitir las consultas fuera del proceso y volver a la cola en ** el mismo proceso **, reparsing the questions y ejecutarlos como declaraciones. Eso suena terriblemente ineficiente e innecesario. No estamos hablando de cruzar entre maestros MySQL o cambiar los motores de almacenamiento. Es impactante que no haya una transferencia binaria intraprocesal eficiente. –
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
en cuenta que hay un comando mysqldbcopy como parte de las utilidades de agregar mysql .... https://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html
Pero requiere la instalación de un paquete adicional: 'apt install mysql-utilities' – Droidzone
Realmente no sé a qué te refieres con "acceso local". Pero para esa solución necesita poder acceder a través del servidor ssh al copiar los archivos donde está almacenada la base de datos.
No puedo usar mysqldump, debido a mi base de datos es grande (7Go, Mysqldump fallar) Si la versión de la base de datos MySQL 2 es demasiado diferente podría no funcionar, se puede comprobar la versión de MySQL usando -V MySQL.
1) Copiar los datos desde el servidor remoto en el equipo local (VPS es el alias a su servidor remoto, puede ser reemplazado por [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) Importación de 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 usted tiene una versión diferente, es posible que tenga que ejecutar
/etc/init.d/mysql stop
mysql_upgrade -u root -pPASSWORD --force #that step took almost 1hrs
/etc/init.d/mysql start
La mejor forma de clonar tablas de bases de datos sin mysqldump:
Crear clon de consultas con la 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';
Run que la producción!
Pero tenga en cuenta, por encima de la escritura sólo tablas clon rápido - no vistas, triggers y la facilidad de funciones: se puede obtener rápidamente la estructura de mysqldump --no-data --triggers -uroot -ppassword
, y luego se utiliza para clonar sólo se inserte comunicado.
¿Por qué es una pregunta real? Porque la carga de mysqldumps es fea lenta si DB es más de 2 Gb. Y no puede clonar tablas InnoDB simplemente copiando archivos DB (como copia de seguridad de instantáneas).
Todas las soluciones anteriores llegan un poco al punto, sin embargo, simplemente no copian todo. Creé una función PHP (aunque algo larga) que copia todo, incluidas tablas, claves externas, datos, vistas, procedimientos, funciones, activadores 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]));
}
}
}
¿Qué pasa con 'mysqldump'? –
La mayoría de las respuestas a continuación recrean mysqldump, que seguramente se romperá en algunos casos ... –
@MichaelMior mysqldump está bien para bases de datos pequeñas pero un volcado reciente de una base de datos altamente indexada me llevará más de 40 horas recuperarme de un volcado. Es por eso que la empresa MySQL tiene una copia de seguridad empresarial, con un precio de $ 5k. PD: Proporcionaré una respuesta que mantenga la integridad referencial al permitirnos usar InnoDB y realizar copias de seguridad y recuperación rápidas. – Quaternion