Vâng, có 2 phương pháp:
Phương pháp 1: Một phương pháp nổi tiếng để đổi tên lược đồ cơ sở dữ liệu là bằng cách loại bỏ lược đồ bằng Mysqldump và khôi phục nó trong một lược đồ khác, sau đó bỏ lược đồ cũ (nếu cần).
Từ Shell
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
Mặc dù phương pháp trên là dễ dàng, nhưng nó tốn thời gian và không gian. Điều gì xảy ra nếu lược đồ lớn hơn 100GB? Có những phương pháp mà bạn có thể ghép các lệnh trên lại với nhau để tiết kiệm không gian, tuy nhiên nó sẽ không tiết kiệm thời gian.
Để khắc phục các tình huống như vậy, có một phương pháp nhanh chóng khác để đổi tên các lược đồ, tuy nhiên, một số lưu ý phải được thực hiện trong khi thực hiện.
Phương pháp 2: MySQL có một tính năng rất tốt để đổi tên các bảng thậm chí hoạt động trên các lược đồ khác nhau. Hoạt động đổi tên này là nguyên tử và không ai khác có thể truy cập vào bảng trong khi nó được đổi tên. Điều này mất một thời gian ngắn để hoàn thành vì việc thay đổi tên của bảng hoặc lược đồ của nó chỉ là thay đổi siêu dữ liệu. Đây là cách tiếp cận thủ tục khi thực hiện đổi tên:
Tạo lược đồ cơ sở dữ liệu mới với tên mong muốn. Đổi tên các bảng từ lược đồ cũ thành lược đồ mới, sử dụng lệnh RENAME TABLE của MySQL. Bỏ lược đồ cơ sở dữ liệu cũ.
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too
. Bẻ khóa RENAME TABLE của MySQL không thành công nếu có các trình kích hoạt tồn tại trên các bảng. Để khắc phục điều này, chúng ta có thể làm những điều sau đây:
1) Dump the triggers, events and stored routines in a separate file.
Điều này được thực hiện bằng cách sử dụng các cờ -E, -R (ngoài -t -d để loại bỏ các kích hoạt) cho lệnh mysqldump. Khi các kích hoạt được kết xuất, chúng ta sẽ cần loại bỏ chúng khỏi lược đồ, để lệnh RENAME TABLE hoạt động.
$ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
2) Tạo danh sách các bảng duy nhất của BASE. Chúng có thể được tìm thấy bằng cách sử dụng một truy vấn trên information_schema.TABLES
bảng.
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
3) Kết xuất các khung nhìn trong một tập tin. Lượt xem có thể được tìm thấy bằng cách sử dụng một truy vấn trên cùng một information_schema.TABLES
bảng.
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) Thả các kích hoạt trên các bảng hiện tại trong old_schema.
mysql> DROP TRIGGER <trigger_name>;
...
5) Khôi phục các tệp kết xuất ở trên một khi tất cả các bảng cơ sở cơ sở được tìm thấy trong bước # 2 được đổi tên.
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
Những rắc rối với các phương thức trên: Chúng tôi có thể cần cập nhật GRANTS cho người dùng sao cho khớp với tên_bảng chính xác. Chúng có thể được sửa với một CẬP NHẬT đơn giản trên các bảng mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db cập nhật tên old_schema thành new_schema và gọi các đặc quyền của Flush; Mặc dù phương thức 2 “có vẻ phức tạp hơn một chút so với phương pháp 1“, nhưng điều này hoàn toàn có thể viết được. Một tập lệnh bash đơn giản để thực hiện các bước trên theo trình tự phù hợp, có thể giúp bạn tiết kiệm không gian và thời gian trong khi đổi tên các lược đồ cơ sở dữ liệu vào lần tới.
Nhóm DBA từ xa Percona đã viết một tập lệnh có tên là rename_db 'hoạt động theo cách sau:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
Để thể hiện việc sử dụng tập lệnh này, đã sử dụng một lược đồ mẫu, emp emp, đã tạo các trình kích hoạt thử nghiệm, các thói quen được lưu trữ trên lược đồ đó. Sẽ cố gắng đổi tên lược đồ cơ sở dữ liệu bằng cách sử dụng tập lệnh, mất vài giây để hoàn thành trái ngược với phương pháp kết xuất / khôi phục tốn thời gian.
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 |
+--------------------+
Như bạn có thể thấy trong kết quả đầu ra ở trên, lược đồ cơ sở dữ liệu, có thể đổi tên thành tên emp empestest trong chưa đầy một giây. Cuối cùng, đây là tập lệnh từ Percona được sử dụng ở trên cho phương thức 2 “.
#!/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