มี 2 วิธี:
วิธีที่ 1:วิธีที่รู้จักกันดีสำหรับการเปลี่ยนชื่อสคีมาฐานข้อมูลคือการดัมพ์สกีมาโดยใช้ Mysqldump และกู้คืนในสคีมาอื่นแล้วปล่อยสคีมาเก่า (ถ้าจำเป็น)
จากเชลล์
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
แม้ว่าวิธีการข้างต้นนั้นง่าย แต่ก็ใช้เวลาและพื้นที่มาก เกิดอะไรขึ้นถ้าคีมามีขนาดเกิน100GB มีวิธีที่คุณสามารถไพพ์คำสั่งข้างต้นเข้าด้วยกันเพื่อประหยัดพื้นที่ได้อย่างไรก็ตามมันจะไม่ประหยัดเวลา
เพื่อแก้ไขสถานการณ์ดังกล่าวมีวิธีการอื่นที่รวดเร็วในการเปลี่ยนชื่อสกีมาอย่างไรก็ตามต้องใช้ความระมัดระวังในขณะที่ทำ
วิธีที่ 2: MySQL มีคุณสมบัติที่ดีมากสำหรับการเปลี่ยนชื่อตารางที่ใช้งานได้กับ schema ที่แตกต่างกัน การดำเนินการเปลี่ยนชื่อนี้เป็นแบบอะตอมมิกและไม่มีใครสามารถเข้าถึงตารางได้ในขณะที่กำลังถูกเปลี่ยนชื่อ การดำเนินการนี้ใช้เวลาสั้น ๆ เนื่องจากการเปลี่ยนชื่อของตารางหรือสคีมาเป็นการเปลี่ยนแปลงข้อมูลเมตาเท่านั้น นี่คือวิธีการขั้นตอนในการเปลี่ยนชื่อ:
สร้างสกีมาฐานข้อมูลใหม่ด้วยชื่อที่ต้องการ เปลี่ยนชื่อตารางจากสคีมาเก่าไปเป็นสคีมาใหม่โดยใช้คำสั่ง“ RENAME TABLE” ของ MySQL ปล่อยคีมาฐานข้อมูลเก่า
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too
. “ RENAME TABLE” ของ MySQL ล้มเหลวหากมีทริกเกอร์อยู่บนตาราง เพื่อแก้ไขปัญหานี้เราสามารถทำสิ่งต่อไปนี้:
1) Dump the triggers, events and stored routines in a separate file.
สิ่งนี้ทำได้โดยใช้แฟล็ก -E, -R (นอกเหนือจาก -t -d ซึ่งดัมพ์ทริกเกอร์) ไปยังคำสั่ง mysqldump เมื่อทริกเกอร์ถูกทิ้งเราจะต้องดรอปจาก schema เพื่อให้คำสั่ง 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)ทิ้งมุมมองในไฟล์ out สามารถดูมุมมองได้โดยใช้แบบสอบถามใน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)กู้คืนไฟล์ดัมพ์ข้างต้นเมื่อตาราง“ Base” ทั้งหมดที่พบในขั้นตอนที่ 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" เพียงเล็กน้อย แต่ก็สามารถเขียนสคริปต์ได้อย่างสมบูรณ์ สคริปต์ทุบตีง่าย ๆ ที่จะทำตามขั้นตอนข้างต้นตามลำดับที่เหมาะสมสามารถช่วยคุณประหยัดพื้นที่และเวลาในขณะที่เปลี่ยนชื่อสกีมาฐานข้อมูลในครั้งต่อไป
ทีม Percona Remote DBA ได้เขียนสคริปต์ชื่อ“ rename_db” ซึ่งทำงานในวิธีต่อไปนี้:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
ในการสาธิตการใช้งานสคริปต์นี้ให้ใช้ตัวอย่าง schema“ emp” ที่สร้างทริกเกอร์ทดสอบสร้างรูทีนที่เก็บไว้ใน schema นั้น จะพยายามเปลี่ยนชื่อสกีมาฐานข้อมูลโดยใช้สคริปต์ซึ่งใช้เวลาสักครู่ในการดำเนินการให้ตรงข้ามกับวิธีการถ่ายโอนข้อมูล / คืนค่าที่ใช้เวลานาน
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” ในเวลาน้อยกว่าหนึ่งวินาที สุดท้ายนี้คือสคริปต์จาก Percona ที่ใช้ด้านบนสำหรับ“ วิธีที่ 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