Cóż, są 2 metody:
Metoda 1: Dobrze znaną metodą zmiany nazwy schematu bazy danych jest zrzucenie schematu za pomocą Mysqldump i przywrócenie go w innym schemacie, a następnie usunięcie starego schematu (w razie potrzeby).
Od Shell
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
Chociaż powyższa metoda jest łatwa, zajmuje dużo czasu i miejsca. Co jeśli schemat jest większy niż 100 GB?Istnieją metody, w których można połączyć powyższe polecenia razem, aby zaoszczędzić miejsce, jednak nie pozwoli to zaoszczędzić czasu.
Aby zaradzić takim sytuacjom, istnieje inna szybka metoda zmiany nazw schematów, jednak należy przy tym zachować ostrożność.
Metoda 2: MySQL ma bardzo dobrą funkcję do zmiany nazw tabel, która działa nawet w różnych schematach. Ta operacja zmiany nazwy ma charakter atomowy i nikt inny nie może uzyskać dostępu do tabeli podczas jej zmiany nazwy. Zajmuje to krótki czas, ponieważ zmiana nazwy tabeli lub jej schematu jest jedynie zmianą metadanych. Oto podejście proceduralne przy zmianie nazwy:
Utwórz nowy schemat bazy danych o żądanej nazwie. Zmień nazwy tabel ze starego schematu na nowy, używając komendy MySQL „RENAME TABLE”. Usuń stary schemat bazy danych.
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too
. MySQL „RENAME TABLE” kończy się niepowodzeniem, jeśli w tabelach istnieją wyzwalacze. Aby temu zaradzić, możemy wykonać następujące czynności:
1) Dump the triggers, events and stored routines in a separate file.
Dokonano tego przy użyciu flag -E, -R (oprócz -t -d, który zrzuca wyzwalacze) do komendy mysqldump. Po zrzuceniu wyzwalaczy będziemy musieli usunąć je ze schematu, aby polecenie RENAME TABLE działało.
$ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
2) Wygeneruj listę tylko tabel „BASE”. Można je znaleźć za pomocą zapytania w information_schema.TABLES
tabeli.
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
3) Zrzuć widoki do pliku wyjściowego. Widoki można znaleźć za pomocą zapytania w tej samej information_schema.TABLES
tabeli.
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) Upuść wyzwalacze na bieżących tabelach w old_schema.
mysql> DROP TRIGGER <trigger_name>;
...
5) Przywróć powyższe pliki zrzutu po zmianie nazwy wszystkich tabel „Podstawowych” znalezionych w kroku # 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
Zawiłości z powyższymi metodami: może być konieczne zaktualizowanie GRANTS dla użytkowników, aby pasowali do poprawnej nazwy schematu. Można to naprawić prostą AKTUALIZACJĄ w tabelach mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db aktualizując nazwę old_schema do new_schema i wywołując „uprawnienia Flush;”. Chociaż „metoda 2” wydaje się nieco bardziej skomplikowana niż „metoda 1”, jest to całkowicie skryptowalne. Prosty skrypt bash do wykonania powyższych kroków we właściwej kolejności może pomóc zaoszczędzić miejsce i czas podczas następnej zmiany nazw schematów bazy danych.
Zespół Percona Remote DBA napisał skrypt o nazwie „rename_db”, który działa w następujący sposób:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
Aby zademonstrować użycie tego skryptu, użyłem przykładowego schematu „emp”, utworzyłem wyzwalacze testowe, zapisałem procedury na tym schemacie. Spróbuje zmienić nazwę schematu bazy danych za pomocą skryptu, którego wypełnienie zajmuje kilka sekund, w przeciwieństwie do czasochłonnej metody zrzutu / przywracania.
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 |
+--------------------+
Jak widać na powyższym wyjściu, schemat bazy danych „emp” został przemianowany na „emp_test” w mniej niż sekundę. Na koniec jest to skrypt z Percony, który został użyty powyżej dla „metody 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