没有本地访问服务器,有没有办法复制/克隆一个MySQL数据库(有内容和没有内容)到另一个不使用mysqldump?
我目前使用的是MySQL 4.0。
没有本地访问服务器,有没有办法复制/克隆一个MySQL数据库(有内容和没有内容)到另一个不使用mysqldump?
我目前使用的是MySQL 4.0。
当前回答
我真的不知道你说的“本地访问”是什么意思。 但是对于这个解决方案,你需要能够通过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
其他回答
Mysqldump是个不错的解决方案。复制数据库的最简单方法:
mysqldump -uusername -ppass dbname1 |MySQL -uusername -ppass dbname2
此外,您可以通过以下方式更改存储引擎:
mysqldump -uusername -ppass dbname1 |sed 's/InnoDB/RocksDB/' |MySQL -uusername -ppass dbname2
实际上,我想在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;
一个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';
所有先前的解都在这一点上,但是,它们并没有完全复制。我创建了一个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克隆数据库表的最好方法:
创建一个新数据库。 使用query创建clone-queries: SET @NewSchema = 'your_new_db'; SET @OldSchema = 'your_exists_db'; SELECT CONCAT('CREATE TABLE ',@NewSchema,')。',table_name,' LIKE ', TABLE_SCHEMA,'.',table_name,';插入',@NewSchema,'。”,table_name“SELECT * FROM”,TABLE_SCHEMA。“table_name,”,”) 从information_schema。TABLE_SCHEMA = @OldSchema AND TABLE_TYPE != 'VIEW'; 运行输出!
但是请注意,上面的脚本只是快速克隆表-而不是视图,触发器和用户函数:你可以通过mysqldump——no-data——triggers -uroot -ppassword快速获得结构,然后使用仅克隆插入语句。
为什么这是实际问题?因为如果DB超过2Gb, mysqldump的上传速度非常慢。你不能仅仅通过复制DB文件来克隆InnoDB表(比如快照备份)。