如果没有对服务器的本地访问权,有没有办法在不使用MySQL数据库的情况下将MySQL数据库(包含内容和不包含内容)复制/克隆到另一个数据库中mysqldump
?
我目前正在使用MySQL 4.0。
CREATE TABLE t2 SELECT * FROM t1;
因为您会丢失索引信息,因此会丢失诸如auto_increment之类的任何特殊内容。许多Google会使用此副本表来进行此类操作,并且会产生不良结果。
如果没有对服务器的本地访问权,有没有办法在不使用MySQL数据库的情况下将MySQL数据库(包含内容和不包含内容)复制/克隆到另一个数据库中mysqldump
?
我目前正在使用MySQL 4.0。
CREATE TABLE t2 SELECT * FROM t1;
因为您会丢失索引信息,因此会丢失诸如auto_increment之类的任何特殊内容。许多Google会使用此副本表来进行此类操作,并且会产生不良结果。
Answers:
我可以看到您说您不想使用mysqldump
,但是在寻找类似解决方案时我到达了此页面,其他人也可能找到它。考虑到这一点,这是一种从Windows服务器的命令行复制数据库的简单方法:
db2
是目标数据库,源数据库db1
将在此复制。mysqldump -h [server] -u [user] -p[password] db1 | mysql -h [server] -u [user] -p[password] db2
注意:-p
和之间没有空格[password]
mysqldump -h [server] -u [user] -p db1 > db1
,mysql -h [server] -u [user] -p db2 < db1
否则密码提示会把它弄乱,至少对我来说是使用腻子时。
mysqldump -u root -p -v db1 | mysql -u root -p db2
两次进入通行证
您可以通过运行以下命令来复制没有数据的表:
CREATE TABLE x LIKE y;
(请参阅MySQL CREATE TABLE Docs)
您可以编写一个脚本,该脚本SHOW TABLES
从一个数据库获取输出,然后将架构复制到另一个数据库。您应该能够引用架构+表名称,例如:
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也有一些脚本,这些脚本可能对同步数据很有帮助。可能不会更快,但是您可以在实时数据上运行它们的同步脚本而无需太多锁定。
如果您使用的是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
echo "set foreign_key_checks = 0; $fCreateTable ; $fInsertData ; set foreign_key_checks = 1;" | mysql $DBCONN $DBNAME
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
在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
请注意,有一个mysqldbcopy命令作为mysql实用程序添加的一部分...。https ://dev.mysql.com/doc/mysql-utilities/1.5/en/utils-task-clone-db.html
apt install mysql-utilities
我真的不知道您所说的“本地访问”是什么意思。但是对于该解决方案,您需要能够通过ssh访问服务器以将文件复制到存储数据库的位置。
我无法使用mysqldump,因为我的数据库很大(7Go,mysqldump失败)。如果2 mysql数据库的版本太不同,可能无法正常工作,则可以使用mysql -V检查mysql版本。
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
所有先前的解决方案都达到了这一点,但是,它们只是不复制所有内容。我创建了一个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
就效率而言,这甚至更糟。
实际上,我想用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;
不使用mysqldump克隆数据库表的最佳方法:
使用查询创建克隆查询:
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';
运行该输出!
但是请注意,上面的脚本只是快速克隆表,而不是视图,触发器和用户功能:您可以通过快速获取结构mysqldump --no-data --triggers -uroot -ppassword
,然后仅用于复制insert语句。
为什么是实际问题?因为如果数据库超过2Gb ,则mysqldumps的上载速度会很慢。而且,您不能仅通过复制数据库文件(例如快照备份)来克隆InnoDB表。
显示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';
mysqldump
?