Как быстро переименовать базу данных MySQL (изменить имя схемы)? - PullRequest
874 голосов
/ 16 сентября 2008

Руководство MySQL на MySQL охватывает это.

Обычно я просто выкидываю базу данных и импортирую ее под новым именем. Это не вариант для очень больших баз данных. Очевидно, RENAME {DATABASE | SCHEMA} db_name TO new_db_name; совершает плохие поступки, существует только в нескольких версиях и в целом является плохой идеей .

Это должно работать с InnoDB , который хранит вещи совсем иначе, чем MyISAM .

Ответы [ 47 ]

15 голосов
/ 14 января 2016

Самый простой и надежный способ сделать полное переименование (включая удаление старой базы данных в конце, чтобы переименовать, а не копию) :

mysqladmin -uroot -pmypassword create newdbname
mysqldump -uroot -pmypassword --routines olddbname | mysql -uroot -pmypassword newdbname
mysqladmin -uroot -pmypassword drop olddbname

Шаги:

  1. Скопируйте строки в Блокнот.
  2. Замените все ссылки на "olddbname", "newdbname", "mypassword" (+ необязательно "root") вашими эквивалентами.
  3. Выполнить по одному в командной строке (при появлении запроса введите «y»).
14 голосов
/ 16 сентября 2008

MySQL в настоящее время не поддерживает переименование базы данных через ее командный интерфейс, но вы можете переименовать базу данных, если у вас есть доступ к каталогу, в котором MySQL хранит свои базы данных. Для установок по умолчанию MySQL это обычно находится в каталоге данных в каталоге, где был установлен MySQL. Найдите в базе данных имя базы данных, которую вы хотите переименовать, и переименуйте ее. Переименование каталога может вызвать проблемы с разрешениями. Будь в курсе.

Примечание: Вы должны остановить MySQL, прежде чем сможете переименовать базу данных

Я бы порекомендовал создать новую базу данных (используя нужное вам имя) и экспортировать / импортировать необходимые данные из старой в новую. Довольно просто.

13 голосов
/ 16 сентября 2008

Когда вы переименовываете базу данных в PHPMyAdmin, она создает дамп, затем удаляет и заново создает базу данных с новым именем.

12 голосов
/ 30 ноября 2012

Для тех, кто является пользователями Mac, Sequel Pro имеет опцию Rename Database в меню Database. http://www.sequelpro.com/

12 голосов
/ 29 января 2014

Ну есть 2 метода:

Метод 1: Хорошо известный метод для переименования схемы базы данных - выгрузка схемы с помощью Mysqldump и восстановление ее в другой схеме, а затем удаление старой схемы (при необходимости).

Из скорлупы

 mysqldump emp > emp.out
 mysql -e "CREATE DATABASE employees;"
 mysql employees < emp.out 
 mysql -e "DROP DATABASE emp;"

Несмотря на то, что описанный выше метод прост, он требует времени и пространства. Что делать, если размер схемы превышает 100 ГБ? Существуют методы, в которых вы можете объединить перечисленные выше команды вместе для экономии места, однако это не сэкономит время.

Для исправления таких ситуаций существует другой быстрый способ переименования схем, однако при этом необходимо соблюдать осторожность.

Метод 2: MySQL имеет очень хорошую функцию для переименования таблиц, которая работает даже в разных схемах. Эта операция переименования является атомарной, и никто другой не может получить доступ к таблице во время ее переименования. Это займет короткое время, так как изменение имени таблицы или ее схемы - это только изменение метаданных. Вот процедурный подход к переименованию:

Создать новую схему базы данных с нужным именем. Переименуйте таблицы из старой схемы в новую, используя команду MySQL «RENAME TABLE». Удалите старую схему базы данных. 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. После сброса триггеров нам нужно будет удалить их из схемы, чтобы команда 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) Сбросить представления в выходной файл. Представления можно найти с помощью запроса к той же таблице 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) Восстановите вышеуказанные файлы дампа, как только все «базовые» таблицы, найденные на шаге №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 для пользователей, чтобы они соответствовали правильному имени схемы. Они могут быть исправлены с помощью простого UPDATE для таблиц mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db, обновляющих имя old_schema до new_schema и вызывающих «Flush privileges;». Хотя «метод 2» кажется немного более сложным, чем «метод 1», он полностью подходит для сценариев. Простой скрипт bash для выполнения вышеуказанных шагов в правильной последовательности поможет сэкономить место и время при следующем переименовании схем базы данных.

Команда Percona Remote DBA написала сценарий «rename_db», который работает следующим образом:

[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>

Чтобы продемонстрировать использование этого скрипта, использовали пример схемы «emp», создали триггеры тестирования, сохранили подпрограммы в этой схеме. Попытается переименовать схему базы данных, используя сценарий, для завершения которого требуется несколько секунд, а не метод, занимающий много времени при дампе / восстановлении.

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
9 голосов
/ 19 мая 2010

Можно переименовать все таблицы в базе данных, чтобы они были в другой базе данных, без необходимости выполнять полный дамп и восстановление.

DROP PROCEDURE IF EXISTS mysql.rename_db;
DELIMITER ||
CREATE PROCEDURE mysql.rename_db(IN old_db VARCHAR(100), IN new_db VARCHAR(100))
BEGIN
SELECT CONCAT('CREATE DATABASE ', new_db, ';') `# create new database`;
SELECT CONCAT('RENAME TABLE `', old_db, '`.`', table_name, '` TO `', new_db, '`.`', table_name, '`;') `# alter table` FROM information_schema.tables WHERE table_schema = old_db;
SELECT CONCAT('DROP DATABASE `', old_db, '`;') `# drop old database`;
END||
DELIMITER ;

$ time mysql -uroot -e "call mysql.rename_db('db1', 'db2');" | mysql -uroot

Однако любые триггеры в целевой БД не будут счастливы. Сначала вам нужно будет удалить их, а затем переименовать.

mysql -uroot -e "call mysql.rename_db('test', 'blah2');" | mysql -uroot
ERROR 1435 (HY000) at line 4: Trigger in wrong schema
8 голосов
/ 09 февраля 2017

Большинство ответов здесь неверны по одной из двух причин:

  1. Вы не можете просто использовать RENAME TABLE, потому что могут быть представления и триггеры. Если есть триггеры, сбой RENAME TABLE
  2. Вы не можете использовать mysqldump, если хотите «быстро» (как было предложено в вопросе) переименовать большую базу данных

У Percona есть запись в блоге о том, как сделать это хорошо: https://www.percona.com/blog/2013/12/24/renaming-database-schema-mysql/

и сценарий, опубликованный (сделанный?) Саймоном Р. Джонсом, который делает то, что предлагается в этом посте. Я исправил ошибку, обнаруженную в скрипте. Вы можете увидеть это здесь:

https://gist.github.com/ryantm/76944318b0473ff25993ef2a7186213d

Вот его копия:

#!/bin/bash
# Copyright 2013 Percona LLC and/or its affiliates
# @see https://www.percona.com/blog/2013/12/24/renaming-database-schema-mysql/
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 "SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = '$2'" -sss`
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

Сохраните его в файл с именем rename_db и сделайте скрипт исполняемым с chmod +x rename_db, затем используйте его как ./rename_db localhost old_db new_db

7 голосов
/ 12 декабря 2008

Вот командный файл, который я написал, чтобы автоматизировать его из командной строки, но для Windows / MS-DOS.

Синтаксис: база данных rename_mysqldb newdatabase -u [пользователь] -p [пароль]

:: ***************************************************************************
:: FILE: RENAME_MYSQLDB.BAT
:: ***************************************************************************
:: DESCRIPTION
:: This is a Windows /MS-DOS batch file that automates renaming a MySQL database 
:: by using MySQLDump, MySQLAdmin, and MySQL to perform the required tasks.
:: The MySQL\bin folder needs to be in your environment path or the working directory.
::
:: WARNING: The script will delete the original database, but only if it successfully
:: created the new copy. However, read the disclaimer below before using.
::
:: DISCLAIMER
:: This script is provided without any express or implied warranties whatsoever.
:: The user must assume the risk of using the script.
::
:: You are free to use, modify, and distribute this script without exception.
:: ***************************************************************************

:INITIALIZE
@ECHO OFF
IF [%2]==[] GOTO HELP
IF [%3]==[] (SET RDB_ARGS=--user=root) ELSE (SET RDB_ARGS=%3 %4 %5 %6 %7 %8 %9)
SET RDB_OLDDB=%1
SET RDB_NEWDB=%2
SET RDB_DUMPFILE=%RDB_OLDDB%_dump.sql
GOTO START

:START
SET RDB_STEP=1
ECHO Dumping "%RDB_OLDDB%"...
mysqldump %RDB_ARGS% %RDB_OLDDB% > %RDB_DUMPFILE%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR_ABORT
SET RDB_STEP=2
ECHO Creating database "%RDB_NEWDB%"...
mysqladmin %RDB_ARGS% create %RDB_NEWDB%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR_ABORT
SET RDB_STEP=3
ECHO Loading dump into "%RDB_NEWDB%"...
mysql %RDB_ARGS% %RDB_NEWDB% < %RDB_DUMPFILE%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR_ABORT
SET RDB_STEP=4
ECHO Dropping database "%RDB_OLDDB%"...
mysqladmin %RDB_ARGS% drop %RDB_OLDDB% --force
IF %ERRORLEVEL% NEQ 0 GOTO ERROR_ABORT
SET RDB_STEP=5
ECHO Deleting dump...
DEL %RDB_DUMPFILE%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR_ABORT
ECHO Renamed database "%RDB_OLDDB%" to "%RDB_NEWDB%".
GOTO END

:ERROR_ABORT
IF %RDB_STEP% GEQ 3 mysqladmin %RDB_ARGS% drop %NEWDB% --force
IF %RDB_STEP% GEQ 1 IF EXIST %RDB_DUMPFILE% DEL %RDB_DUMPFILE%
ECHO Unable to rename database "%RDB_OLDDB%" to "%RDB_NEWDB%".
GOTO END

:HELP
ECHO Renames a MySQL database.
ECHO Usage: %0 database new_database [OPTIONS]
ECHO Options: Any valid options shared by MySQL, MySQLAdmin and MySQLDump.
ECHO          --user=root is used if no options are specified.
GOTO END    

:END
SET RDB_OLDDB=
SET RDB_NEWDB=
SET RDB_ARGS=
SET RDB_DUMP=
SET RDB_STEP=
7 голосов
/ 19 января 2018

шагов:

  1. Хит http://localhost/phpmyadmin/
  2. Выберите вашу БД
  3. Нажмите на вкладку «Операции»
  4. Там будет вкладка «Переименовать базу данных». Добавьте новое имя и установите флажок «Настроить привилегии».
  5. Нажмите на Go.

enter image description here

7 голосов
/ 17 мая 2011

Хранимая процедура TodoInTX для меня не совсем работает Вот мой удар:

-- stored procedure rename_db: Rename a database my means of table copying.
-- Caveats: 
-- Will clobber any existing database with the same name as the 'new' database name.
-- ONLY copies tables; stored procedures and other database objects are not copied.
-- Tomer Altman (taltman@ai.sri.com)

delimiter //
DROP PROCEDURE IF EXISTS rename_db;
CREATE PROCEDURE rename_db(IN old_db VARCHAR(100), IN new_db VARCHAR(100))
BEGIN
    DECLARE current_table VARCHAR(100);
    DECLARE done INT DEFAULT 0;
    DECLARE old_tables CURSOR FOR select table_name from information_schema.tables where table_schema = old_db;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    SET @output = CONCAT('DROP SCHEMA IF EXISTS ', new_db, ';'); 
    PREPARE stmt FROM @output;
    EXECUTE stmt;

    SET @output = CONCAT('CREATE SCHEMA IF NOT EXISTS ', new_db, ';');
    PREPARE stmt FROM @output;
    EXECUTE stmt;

    OPEN old_tables;
    REPEAT
        FETCH old_tables INTO current_table;
        IF NOT done THEN
        SET @output = CONCAT('alter table ', old_db, '.', current_table, ' rename ', new_db, '.', current_table, ';');
        PREPARE stmt FROM @output;
        EXECUTE stmt;

        END IF;
    UNTIL done END REPEAT;

    CLOSE old_tables;

END//
delimiter ;
...