有两种方法:
方法 1: 一种众所周知的重命名数据库架构的方法是使用 Mysqldump 转储架构并将其恢复到另一个架构中,然后删除旧架构(如果需要)。
从外壳
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
上述方法虽然简单,但费时费力。如果架构超过 100GB 怎么办?有一些方法可以将上述命令一起传递以节省空间,但不会节省时间。
为了解决这种情况,还有另一种快速重命名模式的方法,但是,在执行此操作时必须小心。
方法 2: MySQL 有一个非常好的功能可以重命名表,甚至可以跨不同的模式工作。此重命名操作是原子操作,并且在重命名表时没有其他人可以访问该表。这需要很短的时间才能完成,因为更改表的名称或其架构只是元数据更改。以下是重命名的程序方法:
使用所需名称创建新的数据库架构。
使用 MySQL 的“RENAME TABLE”命令将表从旧模式重命名为新模式。
删除旧的数据库模式。
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too。如果表上存在触发器,MySQL 的“重命名表”将失败。为了解决这个问题,我们可以做以下事情:
1) Dump the triggers, events and stored routines in a separate file. 使用 -E、-R 标志(除了 -t -d 转储触发器)到 mysqldump 命令完成。一旦触发器被转储,我们需要将它们从模式中删除,以便 RENAME TABLE 命令起作用。
$ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
2) 生成仅包含“BASE”表的列表。这些可以通过查询information_schema.TABLES 表找到。
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
3) 将视图转储到输出文件中。可以使用对同一个 information_schema.TABLES 表的查询来找到视图。
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='VIEW';
$ mysqldump <database> <view1> <view2> … > views.out
4) 删除 old_schema 中当前表上的触发器。
mysql> DROP TRIGGER <trigger_name>;
...
5) 重命名第 2 步中找到的所有“基本”表后,恢复上述转储文件。
mysql> RENAME TABLE <old_schema>.table_name TO <new_schema>.table_name;
...
$ mysql <new_schema> < views.out
$ mysql <new_schema> < stored_routines_triggers_events.out
上述方法的复杂性:我们可能需要为用户更新 GRANTS,以便他们匹配正确的 schema_name。这些可以通过对 mysql.columns_priv、mysql.procs_priv、mysql.tables_priv、mysql.db 表的简单更新来修复,将 old_schema 名称更新为 new_schema 并调用“刷新权限;”。虽然“方法 2”似乎比“方法 1”复杂一些,但这是完全可以编写脚本的。一个简单的 bash 脚本以正确的顺序执行上述步骤,可以帮助您在下次重命名数据库模式时节省空间和时间。
Percona Remote DBA 团队编写了一个名为“rename_db”的脚本,其工作方式如下:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
为了演示此脚本的使用,使用了示例架构“emp”,创建了测试触发器,并在该架构上存储了例程。将尝试使用脚本重命名数据库架构,这需要几秒钟才能完成,而不是耗时的转储/恢复方法。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| emp |
| mysql |
| performance_schema |
| test |
+--------------------+
[root@dba ~]# time /tmp/rename_db localhost emp emp_test
create database emp_test DEFAULT CHARACTER SET latin1
drop trigger salary_trigger
rename table emp.__emp_new to emp_test.__emp_new
rename table emp._emp_new to emp_test._emp_new
rename table emp.departments to emp_test.departments
rename table emp.dept to emp_test.dept
rename table emp.dept_emp to emp_test.dept_emp
rename table emp.dept_manager to emp_test.dept_manager
rename table emp.emp to emp_test.emp
rename table emp.employees to emp_test.employees
rename table emp.salaries_temp to emp_test.salaries_temp
rename table emp.titles to emp_test.titles
loading views
loading triggers, routines and events
Dropping database emp
real 0m0.643s
user 0m0.053s
sys 0m0.131s
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| emp_test |
| mysql |
| performance_schema |
| test |
+--------------------+
正如您在上面的输出中看到的那样,数据库模式“emp”在不到一秒的时间内被重命名为“emp_test”。最后,这是上面用于“方法 2”的 Percona 脚本。
#!/bin/bash
# Copyright 2013 Percona LLC and/or its affiliates
set -e
if [ -z "$3" ]; then
echo "rename_db <server> <database> <new_database>"
exit 1
fi
db_exists=`mysql -h $1 -e "show databases like '$3'" -sss`
if [ -n "$db_exists" ]; then
echo "ERROR: New database already exists $3"
exit 1
fi
TIMESTAMP=`date +%s`
character_set=`mysql -h $1 -e "show create database $2\G" -sss | grep ^Create | awk -F'CHARACTER SET ' '{print $2}' | awk '{print $1}'`
TABLES=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='BASE TABLE'" -sss`
STATUS=$?
if [ "$STATUS" != 0 ] || [ -z "$TABLES" ]; then
echo "Error retrieving tables from $2"
exit 1
fi
echo "create database $3 DEFAULT CHARACTER SET $character_set"
mysql -h $1 -e "create database $3 DEFAULT CHARACTER SET $character_set"
TRIGGERS=`mysql -h $1 $2 -e "show triggers\G" | grep Trigger: | awk '{print $2}'`
VIEWS=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='VIEW'" -sss`
if [ -n "$VIEWS" ]; then
mysqldump -h $1 $2 $VIEWS > /tmp/${2}_views${TIMESTAMP}.dump
fi
mysqldump -h $1 $2 -d -t -R -E > /tmp/${2}_triggers${TIMESTAMP}.dump
for TRIGGER in $TRIGGERS; do
echo "drop trigger $TRIGGER"
mysql -h $1 $2 -e "drop trigger $TRIGGER"
done
for TABLE in $TABLES; do
echo "rename table $2.$TABLE to $3.$TABLE"
mysql -h $1 $2 -e "SET FOREIGN_KEY_CHECKS=0; rename table $2.$TABLE to $3.$TABLE"
done
if [ -n "$VIEWS" ]; then
echo "loading views"
mysql -h $1 $3 < /tmp/${2}_views${TIMESTAMP}.dump
fi
echo "loading triggers, routines and events"
mysql -h $1 $3 < /tmp/${2}_triggers${TIMESTAMP}.dump
TABLES=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='BASE TABLE'" -sss`
if [ -z "$TABLES" ]; then
echo "Dropping database $2"
mysql -h $1 $2 -e "drop database $2"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.columns_priv where db='$2'" -sss` -gt 0 ]; then
COLUMNS_PRIV=" UPDATE mysql.columns_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.procs_priv where db='$2'" -sss` -gt 0 ]; then
PROCS_PRIV=" UPDATE mysql.procs_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.tables_priv where db='$2'" -sss` -gt 0 ]; then
TABLES_PRIV=" UPDATE mysql.tables_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.db where db='$2'" -sss` -gt 0 ]; then
DB_PRIV=" UPDATE mysql.db set db='$3' WHERE db='$2';"
fi
if [ -n "$COLUMNS_PRIV" ] || [ -n "$PROCS_PRIV" ] || [ -n "$TABLES_PRIV" ] || [ -n "$DB_PRIV" ]; then
echo "IF YOU WANT TO RENAME the GRANTS YOU NEED TO RUN ALL OUTPUT BELOW:"
if [ -n "$COLUMNS_PRIV" ]; then echo "$COLUMNS_PRIV"; fi
if [ -n "$PROCS_PRIV" ]; then echo "$PROCS_PRIV"; fi
if [ -n "$TABLES_PRIV" ]; then echo "$TABLES_PRIV"; fi
if [ -n "$DB_PRIV" ]; then echo "$DB_PRIV"; fi
echo " flush privileges;"
fi