Bene ci sono 2 metodi:
Metodo 1: un metodo ben noto per rinominare lo schema del database consiste nello scaricare lo schema usando Mysqldump e ripristinarlo in un altro schema, quindi rilasciare il vecchio schema (se necessario).
Da Shell
mysqldump emp > emp.out
mysql -e "CREATE DATABASE employees;"
mysql employees < emp.out
mysql -e "DROP DATABASE emp;"
Sebbene il metodo sopra descritto sia semplice, richiede tempo e spazio. Cosa succede se lo schema supera i 100 GB?Esistono metodi in cui è possibile reindirizzare i comandi precedenti per risparmiare spazio, tuttavia non si risparmia tempo.
Per porre rimedio a tali situazioni, esiste un altro metodo rapido per rinominare gli schemi, tuttavia è necessario prestare attenzione mentre lo si fa.
Metodo 2: MySQL ha un'ottima funzionalità per rinominare le tabelle che funziona anche su schemi diversi. Questa operazione di ridenominazione è atomica e nessun altro può accedere alla tabella mentre viene rinominato. Questa operazione richiede poco tempo poiché la modifica del nome di una tabella o del suo schema è solo una modifica dei metadati. Ecco un approccio procedurale nel fare la ridenominazione:
Creare il nuovo schema del database con il nome desiderato. Rinomina le tabelle dal vecchio schema al nuovo schema, usando il comando "RENAME TABLE" di MySQL. Elimina il vecchio schema del database.
If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too
. "RENAME TABLE" di MySQL ha esito negativo se sono presenti trigger nelle tabelle. Per porre rimedio a ciò possiamo fare le seguenti cose:
1) Dump the triggers, events and stored routines in a separate file.
Questo è stato fatto usando i flag -E, -R (oltre a -t -d che scarica i trigger) al comando mysqldump. Una volta scaricati i trigger, dovremo eliminarli dallo schema, affinché il comando RENAME TABLE funzioni.
$ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
2) Generare un elenco di sole tabelle "BASE". Questi possono essere trovati usando una query sulla information_schema.TABLES
tabella.
mysql> select TABLE_NAME from information_schema.tables where
table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
3) Scarica le viste in un file di uscita. Le viste possono essere trovate usando una query sulla stessa information_schema.TABLES
tabella.
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) Rilascia i trigger sulle tabelle correnti in old_schema.
mysql> DROP TRIGGER <trigger_name>;
...
5) Ripristinare i file di dump di cui sopra dopo aver rinominato tutte le tabelle "Base" trovate nel passaggio 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
Intrecci con i metodi di cui sopra: potrebbe essere necessario aggiornare i GRANTS per gli utenti in modo che corrispondano al nome_schema corretto. Questi potrebbero essere risolti con un semplice AGGIORNAMENTO sulle tabelle mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db aggiornando il nome old_schema in new_schema e chiamando "Flush privileges;". Anche se il "metodo 2" sembra un po 'più complicato del "metodo 1", questo è totalmente programmabile. Un semplice script bash per eseguire i passaggi precedenti nella sequenza corretta, può aiutarti a risparmiare spazio e tempo durante la ridenominazione degli schemi di database la prossima volta.
Il team DBA di Percona Remote ha scritto uno script chiamato "rename_db" che funziona nel modo seguente:
[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>
Per dimostrare l'uso di questo script, è stato utilizzato uno schema di esempio "emp", creato trigger di test, routine memorizzate su quello schema. Tenterà di rinominare lo schema del database utilizzando lo script, che richiede alcuni secondi per il completamento rispetto al metodo di dump / ripristino che richiede tempo.
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 |
+--------------------+
Come puoi vedere nell'output sopra, lo schema del database "emp" è stato rinominato in "emp_test" in meno di un secondo. Infine, questo è lo script di Percona che viene usato sopra per "metodo 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