大家好:
現在分享一下最近的一個測試。
大家都知道,在mysql裏面,沒有提供重命名一個數據庫的語句(其實在MySQL 5.1.7 to 5.1.23也有使用過rename database,但是因爲很多的危險性,之後的版本就摒棄了這個功能),那麼如何在mysql數據庫中高效的重命名一個數據庫呢?
1、使用mysqldump備份出數據庫,之後刪除原來的數據庫,再dump文件中修改舊數據庫名稱爲新的名稱,再導入數據庫,修改數據庫中的相關用戶權限(mysqldump的參數必須包含視圖、觸發器、函數、存儲過程等,這裏不再說明了)
1 3 4 | [root@percona ~]# mysqldump emp > emp.out [root@percona ~]# mysql -e "CREATE DATABASE employees;" [root@percona ~]# mysql employees < emp.out [root@percona ~]# mysql -e "DROP DATABASE emp;" |
優點:操作比較簡單,不易出錯
弊端:在遇到數據庫較大的時候,時間和磁盤空間都會有很高的要求
2、利用renametable的方式實現數據庫重命名
主要操作步驟:
A)新建數據庫:create database
B)重命名舊數據庫中的表到新的數據庫中,包含視圖、觸發器等:rename table
C)刪除舊數據庫
D)重授權相關用戶的權限
因爲操作較爲複雜,先附上兩個腳本,rename_db.sh完成數據庫表、觸發器、事件、函數、存儲過程,rename_grants.sh完成相關用戶的授權轉換
腳本執行方法:
A)bash rename_db.sh localhost old_database_name new_database_name
B)bash rename_grants old_database_name new_database_name
注:如果要使用的話,可以自己先測試一下,看看是否有問題,歡迎修改腳本和指正
看不見附件,貼出來了
1、rename_db.sh
#!/bin/bash
# Copyright 2013 zhujzhuo
. ~/.bash_profile > /dev/null 2>&1
if [ $# -lt 3 ]; then
echo "rename_db <server> <database> <new_database>"
exit 1
fi
old_db_exists=`mysql -h $1 -e "show databases like '$2'" -sss `
if [ -z "$old_db_exists" ]; then
echo "ERROR: Old database not exists $2"
exit 1
fi
db_exists=`mysql -h $1 -s -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 $0 $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
if [ -n $TRIGGERS ];then
for TRIGGER in $TRIGGERS ; do
echo "drop trigger $TRIGGER"
/usr/bin/mysql -h $1 $2 -e "drop trigger $TRIGGER"
done
fi
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
2、rename_grants.sh
#!/bin/bash
DATE=`date +%Y%m%d`
if [ -f "/tmp/grants$DATE.sql" ];then
rm -fr /tmp/grants$DATE.sql;
fi
for i in `mysql -N -s -e "select concat(\"show grants for '\",user,\"'@'\",host,\"';\") from mysql.user"|grep -w 'show grants'| mysql -N |grep -w 'GRANT'| sed 's/$/;/g' | grep $1 | awk -F'TO' '{print $2}'`;do mysql -N -s -e "show grants for $i"|grep -w 'GRANT'| sed 's/$/;/g' >> /tmp/grants$DATE.sql;done
if [ -f "/tmp/grants$DATE.sql" ];then
sed -i "s/$1/$2/g" /tmp/grants$DATE.sql;
fi
for i in `mysql -N -s -e "select concat(\"show grants for '\",user,\"'@'\",host,\"';\") from mysql.user"|grep -w 'show grants'| mysql -N |grep -w 'GRANT'| sed 's/$/;/g' | grep $1 | awk -F'TO' '{print $2}'`;do mysql -N -s -e "drop user $i" ;done
mysql < /tmp/grants$DATE.sql