Peki 2 yöntem vardır:
Yöntem 1: Veritabanı şemasını yeniden adlandırmak için iyi bilinen bir yöntem şemayı Mysqldump kullanarak boşaltıp başka bir şemaya geri yüklemek ve sonra eski şemayı (gerekirse) bırakmaktır.
Shell isimli ev sahibinden
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
Yukarıdaki yöntem kolay olsa da, zaman ve alan tüketir. Şema 100 GB'den fazlaysa ne olur ? Yerden tasarruf etmek için yukarıdaki komutları birbirine bağlayabileceğiniz yöntemler vardır, ancak zaman kazanmaz.
Bu gibi durumları gidermek için, şemaları yeniden adlandırmak için başka bir hızlı yöntem vardır, ancak bunu yaparken biraz dikkat edilmelidir.
Yöntem 2: MySQL, farklı şemalarda bile çalışan tabloları yeniden adlandırmak için çok iyi bir özelliğe sahiptir. Bu yeniden adlandırma işlemi atomiktir ve başka hiç kimse yeniden adlandırılırken tabloya erişemez. Tablonun adını veya şemasını değiştirmek yalnızca bir meta veri değişikliği olduğundan bu işlemin tamamlanması kısa bir zaman alır. İşte yeniden adlandırmada prosedürel yaklaşım:
İstediğiniz adla yeni veritabanı şemasını oluşturun. MySQL'in “RENAME TABLE” komutunu kullanarak tabloları eski şemadan yeni şemaya yeniden adlandırın. Eski veritabanı şemasını bırakın.
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too
. Tablolarda tetikleyiciler varsa MySQL'in “RENAME TABLE” başarısız oluyor. Bunu düzeltmek için aşağıdakileri yapabiliriz:
1) Dump the triggers, events and stored routines in a separate file.
Bu, mysqldump komutuna -E, -R bayrakları (tetikleyicileri döken -t -d'ye ek olarak) kullanılarak yapılır. Tetikleyiciler boşaltıldıktan sonra, RENAME TABLE komutunun çalışması için bunları şemadan bırakmamız gerekir.
$ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
2) Yalnızca “BASE” tablolarının bir listesini oluşturun. Bunlar information_schema.TABLES
tablodaki bir sorgu kullanılarak bulunabilir .
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
3) Görünümleri bir çıkış dosyasına dökün. Görünümler, aynı information_schema.TABLES
tablodaki bir sorgu kullanılarak bulunabilir .
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) Tetikleyicileri old_schema içindeki geçerli tablolara bırakın.
mysql> DROP TRIGGER <trigger_name>;
...
5) 2. adımda bulunan tüm “Base” tabloları yeniden adlandırıldıktan sonra yukarıdaki döküm dosyalarını geri yükleyin.
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
Yukarıdaki yöntemlerle ilgili karışıklıklar: Kullanıcılar için GRANTS'ı doğru şema_adı ile eşleşecek şekilde güncellememiz gerekebilir. Bunlar mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, old_schema adını new_schema olarak güncelleyen ve “Flush ayrıcalıkları” olarak adlandırılan basit bir UPDATE ile düzeltilebilir. “Yöntem 2”, “yöntem 1” den biraz daha karmaşık görünse de, bu tamamen yazılabilir niteliktedir. Yukarıdaki adımları uygun sırayla gerçekleştirmek için basit bir bash betiği, bir dahaki sefere veritabanı şemalarını yeniden adlandırırken yerden ve zamandan tasarruf etmenize yardımcı olabilir.
Percona Remote DBA ekibi, aşağıdaki şekilde çalışan “rename_db” adlı bir komut dosyası yazdı:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
Bu komut dosyasının kullanımını göstermek için, örnek bir “emp” şeması kullandı, test tetikleyicileri oluşturdu, o şemada rutinleri sakladı. Zaman alan döküm / geri yükleme yönteminin aksine tamamlanması birkaç saniye süren komut dosyasını kullanarak veritabanı şemasını yeniden adlandırmaya çalışacaktır.
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 |
+--------------------+
Yukarıdaki çıktıda da görebileceğiniz gibi “emp” veritabanı şeması bir saniyeden daha kısa sürede “emp_test” olarak yeniden adlandırıldı. Son olarak, Percona'nın yukarıda “yöntem 2” için kullanılan betiğidir.
#!/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