1. 脚本输出背景
因为mysql 没有提供原生的 rename database (其实在5.1.7时引入了该命令,但是因为一些问题在5.1.23又废弃了)。所以如果我们想对数据库重命名的话,可能大多数人都会想到 使用 mysqldump 导出然后重新导入,但是数据库越大,这个过程耗时就越长。为了能快速的完成 rename database 就有了下面的脚本。
NOTE: 后续脚本如果有变更,会及时上传,如果脚本使用中出现问题,可以给我留言(留下联系方式)。
2. 脚本使用注意事项
# 该脚本很简单,只需提供 5 个参数(必须是5个参数)
Usage: ./rename_database.sh
For example: ./rename_database.sh user password 127.0.0.1 databasename_old database_new
NOTE: 为了安全起见,脚本中注释掉了自动删除 databasename_old 库的代码
3. rename database 脚本
#!/bin/bash
##Script function
# The script is used to rename database of mysql. The script has been tested in the version 5.6 and 5.7 of mysql.
##Script instructions
start=`date +%s`
TIMESTAMP=`date +%s`
set -e
if [ "$1"x = "--help"x ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo "Usage: $0 "
echo "For example: $0 user password 127.0.0.1 databasename_old database_new"
echo "Please try again"
echo -e "-----------------------------------------------------------------------------------------\n"
exit 1
elif [ $# -ne 5 ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo "Usage: $0 "
echo "For example: $0 user password 127.0.0.1 databasename_old database_new"
echo "Please try again"
echo -e "-----------------------------------------------------------------------------------------\n"
exit 1
fi
##set password for mysql login
export MYSQL_PWD=$2
##Check whether the new database is exist
db_exists=`mysql -u $1 -h $3 -e "show databases like '$5'" -sss`
if [ -n "$db_exists" ]; then
echo "ERROR: New database $5 already exists"
exit 1
fi
##Check the character set of the old database
character_set=`mysql -u $1 -h $3 -e "show create database $4\G" -sss| grep ^Create | awk -F'CHARACTER SET ' '{print $2}' | awk '{print $1}'`
##Calculate the number of tables(BASE TABLE),triggers,procedures,functions,views in the old database
echo -e "\n-----------------------------------------------------------------------------------------"
echo "Calculate the number of tables(BASE TABLE),triggers,procedures,functions,views in the old database:"
echo -e "-----------------------------------------------------------------------------------------\n"
TABLES_OLD=`mysql -u $1 -h $3 -e "select count(1) from information_schema.tables where table_schema='$4' and TABLE_TYPE='BASE TABLE'" -sss`
echo "There are $TABLES_OLD BASE TABLES in $4"
VIEWS_OLD=`mysql -u $1 -h $3 -e "select count(1) from information_schema.views where TABLE_SCHEMA='$4'" -sss`
echo "There are $VIEWS_OLD VIEWS in $4"
TRIGGERS_OLD=`mysql -u $1 -h $3 -e "select count(1) from information_schema.triggers where TRIGGER_SCHEMA='$4'" -sss`
echo "There are $TRIGGERS_OLD TRIGGERS in $4"
PROCEDURES_OLD=`mysql -u $1 -h $3 -e "select count(1) from mysql.proc where type='PROCEDURE' and db='$4'" -sss`
echo "There are $PROCEDURES_OLD PROCEDURES in $4"
FUNCTIONS_OLD=`mysql -u $1 -h $3 -e "select count(1) from mysql.proc where type='FUNCTION' and db='$4'" -sss`
echo "There are $FUNCTIONS_OLD FUNCTIONS in $4"
echo -e "-----------------------------------------------------------------------------------------\n"
##Check if you can get table information from the old database
TABLES=`mysql -u $1 -h $3 -e "select TABLE_NAME from information_schema.tables where table_schema='$4' and TABLE_TYPE='BASE TABLE'" -sss`
STATUS=$?
if [ "$STATUS" != 0 ] || [ -z "$TABLES" ]; then
echo "Error retrieving tables from $4"
exit 1
fi
##Create new database
echo -e "\n-----------------------------------------------------------------------------------------"
echo "create database $5 DEFAULT CHARACTER SET $character_set"
echo -e "-----------------------------------------------------------------------------------------\n"
mysql -u $1 -h $3 -e "create database $5 DEFAULT CHARACTER SET $character_set"
##Dump the view definition in old database if exist
VIEWS=`mysql -u $1 -h $3 -e "select TABLE_NAME from information_schema.tables where table_schema='$4' and TABLE_TYPE='VIEW'" -sss`
if [ -n "$VIEWS" ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
mysqldump -u $1 -h $3 $4 --set-gtid-purged=OFF $VIEWS > /tmp/${4}_views${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo "Dump the view successful in /tmp/${4}_views${TIMESTAMP}.dump"
else
echo "Error: !!! Dump view failed"
fi
echo -e "-----------------------------------------------------------------------------------------\n"
fi
##Dump triggers in old database and drop triggers in old database if exist
## We must drop the triggers on the table of old database,else execute "rename table" command on the table with trigger we will encounter the below error
##ERROR 1435 (HY000): Trigger in wrong schema
#TRIGGERS=`mysql -u $1 -h $3 $4 -e "show triggers\G"| grep Trigger: | awk '{print $2}' `
TRIGGERS=`mysql -u $1 -h $3 $4 -e "select TRIGGER_NAME from information_schema.triggers where TRIGGER_SCHEMA='$4'\G"| grep TRIGGER_NAME: | awk '{print $2}' `
if [ -n "$TRIGGERS" ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo -e "Dump and Drop triggers "
echo -e "-----------------------------------------------------------------------------------------"
#mysqldump -u $1 -h $3 $4 -d -t -R -E > /tmp/${4}_trig_pro_fun${TIMESTAMP}.dump
for TRIGGER in $TRIGGERS; do
mysql -u $1 -h $3 $4 -e "show create trigger $TRIGGER\G" >> /tmp/${4}_triggers${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo "drop trigger $TRIGGER"
mysql -u $1 -h $3 $4 -e "drop trigger $TRIGGER"
else
echo -e "Error: !!!Dump the $TRIGGER failed, the script is terminated"
exit 1
fi
done
echo -e "\nDump the TRIGGER successful in /tmp/${4}_trig_pro_fun${TIMESTAMP}.dump"
sed -i '/Trigger/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/sql_mode/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/character_set_client/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/collation_connection/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/Database Collation/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/row in set/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/ERROR:/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/No query specified/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '/\*/d' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i 's/SQL Original Statement://g' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i '1i\delimiter @@' /tmp/${4}_triggers${TIMESTAMP}.dump
sed -i 's/end/end @@/ig' /tmp/${4}_triggers${TIMESTAMP}.dump
fi
##Dump function,procedure,event in old database if exist
echo -e "-----------------------------------------------------------------------------------------\n"
if [ $PROCEDURES_OLD -gt 0 -o $FUNCTIONS_OLD -gt 0 ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo -e "Dump function and procedure in $4 "
echo -e "-----------------------------------------------------------------------------------------"
mysqldump -u $1 -h $3 $4 -d -t -R -E --set-gtid-purged=OFF --skip-triggers > /tmp/${4}_pro_fun${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo -e "Dump the Function and Procedure successful in /tmp/${4}_pro_fun${TIMESTAMP}.dump"
else
echo -e "Error: !!!Function and Procedure dump failed, requiring manual intervention"
fi
fi
##Rename table name
echo -e "\n\n-----------------------------------------------------------------------------------------"
echo "Begin rename tables ......"
echo -e "-----------------------------------------------------------------------------------------"
for TABLE in $TABLES; do
echo "rename table $4.$TABLE to $5.$TABLE"
mysql -u $1 -h $3 $4 -e "SET FOREIGN_KEY_CHECKS=0; rename table $4.$TABLE to $5.$TABLE"
if [ $? != 0 ]; then
echo "Error: !!!$4.$TABLE rename to $5.$TABLE failed"
echo "Error: !!!Only part of the tables in $4 have been renamed successfully, requiring manual intervention (note the trigger)"
exit 1
fi
done
echo -e "-----------------------------------------------------------------------------------------\n"
##Load views to new database
if [ -n "$VIEWS" ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo -e "Begin loading views to new database $5......"
mysql -u $1 -h $3 $5 < /tmp/${4}_views${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo -e "Load views to new database $5 successful"
else
echo -e "Error: !!!load views to $5 failed, requiring manual intervention"
fi
echo -e "-----------------------------------------------------------------------------------------\n"
fi
##Load triggers,procedures,functions to new database
if [ $PROCEDURES_OLD -gt 0 -o $FUNCTIONS_OLD -gt 0 ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo "Begin loading routines and events to new database $5......"
mysql -u $1 -h $3 $5 < /tmp/${4}_pro_fun${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo -e "Load routines and events to new database $5 successful"
else
echo -e "Error: !!!load routines and events to $5 failed, requiring manual intervention"
fi
echo -e "-----------------------------------------------------------------------------------------\n"
fi
if [ -n "$TRIGGERS" ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo "Begin loading triggers to new database $5 ......"
mysql -u $1 -h $3 $5 < /tmp/${4}_triggers${TIMESTAMP}.dump
if [ $? = 0 ]; then
echo -e "Load triggers to new database $5 successful"
else
echo -e "Error: !!!load triggers to $5 failed, requiring manual intervention"
fi
echo -e "-----------------------------------------------------------------------------------------\n"
fi
##Check whether the number of table,view,triggers,procedures,functions in old database and new database is consistent.
echo -e "\n-----------------------------------------------------------------------------------------"
echo -e "Check whether the number of table,view,triggers,procedures,functions in old database and new database is consistent."
TABLES_NEW=`mysql -u $1 -h $3 -e "select count(1) from information_schema.tables where table_schema='$5' and TABLE_TYPE='BASE TABLE'" -sss `
if [ $TABLES_OLD -ne $TABLES_NEW ]; then
echo -e "WARNING: The number of tables in database $4 and database $5 is not equal, please review!!!\n\n"
fi
VIEWS_NEW=`mysql -u $1 -h $3 -e "select count(1) from information_schema.views where TABLE_SCHEMA='$5'" -sss`
if [ $VIEWS_OLD -ne $VIEWS_NEW ]; then
echo "WARNING: The number of views in database $4 and database $5 is not equal, please review!!!\n\n"
fi
TRIGGERS_NEW=`mysql -u $1 -h $3 -e "select count(1) from information_schema.triggers where TRIGGER_SCHEMA='$5'" -sss`
if [ $TRIGGERS_OLD -ne $TRIGGERS_NEW ]; then
echo "WARNING: The number of triggers in database $4 and database $5 is not equal, please review!!!\n\n"
fi
PROCEDURES_NEW=`mysql -u $1 -h $3 -e "select count(1) from mysql.proc where type='PROCEDURE' and db='$5'" -sss`
if [ $PROCEDURES_OLD -ne $PROCEDURES_NEW ]; then
echo "WARNING: The number of triggers in database $4 and database $5 is not equal, please review!!!\n\n"
fi
FUNCTIONS_NEW=`mysql -u $1 -h $3 -e "select count(1) from mysql.proc where type='FUNCTION' and db='$5'" -sss`
if [ $FUNCTIONS_OLD -ne $FUNCTIONS_NEW ]; then
echo "WARNING: The number of functions in database $4 and database $5 is not equal, please review!!!\n\n"
fi
echo -e "-----------------------------------------------------------------------------------------\n"
##Drop the old database
#TABLES=`mysql -u $1 -h $3 -e "select TABLE_NAME from information_schema.tables where table_schema='$4' and TABLE_TYPE='BASE TABLE'" -sss`
#if [ -z "$TABLES" ]; then
# echo -e "\n-----------------------------------------------------------------------------------------"
# echo "Dropping database $4"
# mysql -u $1 -p$2 -h $3 $4 -e "drop database $4" 2>/dev/null
# echo -e "-----------------------------------------------------------------------------------------\n"
#fi
##Process the privileges for new database
if [ `mysql -u $1 -p$2 -h $3 -e "select count(*) from mysql.columns_priv where db='$4'" -sss 2>/dev/null` -gt 0 ]; then
COLUMNS_PRIV=" UPDATE mysql.columns_priv set db='$5' WHERE db='$4';"
fi
if [ `mysql -u $1 -p$2 -h $3 -e "select count(*) from mysql.procs_priv where db='$4'" -sss 2>/dev/null` -gt 0 ]; then
PROCS_PRIV=" UPDATE mysql.procs_priv set db='$5' WHERE db='$4';"
fi
if [ `mysql -u $1 -p$2 -h $3 -e "select count(*) from mysql.tables_priv where db='$4'" -sss 2>/dev/null` -gt 0 ]; then
TABLES_PRIV=" UPDATE mysql.tables_priv set db='$5' WHERE db='$4';"
fi
if [ `mysql -u $1 -p$2 -h $3 -e "select count(*) from mysql.db where db='$4'" -sss 2>/dev/null` -gt 0 ]; then
DB_PRIV=" UPDATE mysql.db set db='$5' WHERE db='$4';"
fi
if [ -n "$COLUMNS_PRIV" ] || [ -n "$PROCS_PRIV" ] || [ -n "$TABLES_PRIV" ] || [ -n "$DB_PRIV" ]; then
echo -e "\n-----------------------------------------------------------------------------------------"
echo "IF you want to change the privileges to new database you need to run all output below:"
echo -e "-----------------------------------------------------------------------------------------"
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;"
echo -e "-----------------------------------------------------------------------------------------"
fi
##Compute the time elapsed of the shell
finished=`date +%s`
echo -e "\n-----------------------------------------------------------------------------------------"
echo -e "The operation of rename database $4 to $5 completed"
elapsed_time=$(($finished - $start))
echo -e "It took $elapsed_time s to rename the database $4"
echo -e "-----------------------------------------------------------------------------------------\n"