How do I quickly rename a MySQL database (change schema name)?

前端 未结 30 2404
余生分开走
余生分开走 2020-11-22 14:54

The MySQL manual at MySQL covers this.

Usually I just dump the database and reimport it with a new name. This is not an option for very big databases. Apparently

相关标签:
30条回答
  • 2020-11-22 15:23

    The simple way

    Change to the database directory:

    cd /var/lib/mysql/
    

    Shut down MySQL... This is important!

    /etc/init.d/mysql stop
    

    Okay, this way doesn't work for InnoDB or BDB-Databases.

    Rename database:

    mv old-name new-name
    

    ...or the table...

    cd database/
    
    mv old-name.frm new-name.frm
    
    mv old-name.MYD new-name.MYD
    
    mv old-name.MYI new-name.MYI
    

    Restart MySQL

    /etc/init.d/mysql start
    

    Done...

    OK, this way doesn't work with InnoDB or BDB databases. In this case you have to dump the database and re-import it.

    0 讨论(0)
  • 2020-11-22 15:23

    You may use this shell script:

    Reference: How to rename a MySQL database?

    #!/bin/bash
    set -e # terminate execution on command failure
    
    mysqlconn="mysql -u root -proot"
    olddb=$1
    newdb=$2
    $mysqlconn -e "CREATE DATABASE $newdb"
    params=$($mysqlconn -N -e "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES \
                               WHERE table_schema='$olddb'")
    for name in $params; do
          $mysqlconn -e "RENAME TABLE $olddb.$name to $newdb.$name";
    done;
    $mysqlconn -e "DROP DATABASE $olddb"
    

    It's working:

    $ sh rename_database.sh oldname newname
    
    0 讨论(0)
  • 2020-11-22 15:23

    Well there are 2 methods:

    Method 1: A well-known method for renaming database schema is by dumping the schema using Mysqldump and restoring it in another schema, and then dropping the old schema (if needed).

    From Shell

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

    Although the above method is easy, it is time and space consuming. What if the schema is more than a 100GB? There are methods where you can pipe the above commands together to save on space, however it will not save time.

    To remedy such situations, there is another quick method to rename schemas, however, some care must be taken while doing it.

    Method 2: MySQL has a very good feature for renaming tables that even works across different schemas. This rename operation is atomic and no one else can access the table while its being renamed. This takes a short time to complete since changing a table’s name or its schema is only a metadata change. Here is procedural approach at doing the rename:

    Create the new database schema with the desired name. Rename the tables from old schema to new schema, using MySQL’s “RENAME TABLE” command. Drop the old database schema. If there are views, triggers, functions, stored procedures in the schema, those will need to be recreated too. MySQL’s “RENAME TABLE” fails if there are triggers exists on the tables. To remedy this we can do the following things :

    1) Dump the triggers, events and stored routines in a separate file. This done using -E, -R flags (in addition to -t -d which dumps the triggers) to the mysqldump command. Once triggers are dumped, we will need to drop them from the schema, for RENAME TABLE command to work.

     $ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out
    

    2) Generate a list of only “BASE” tables. These can be found using a query on information_schema.TABLES table.

     mysql> select TABLE_NAME from information_schema.tables where 
        table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';
    

    3) Dump the views in an out file. Views can be found using a query on the same information_schema.TABLES table.

    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) Drop the triggers on the current tables in the old_schema.

    mysql> DROP TRIGGER <trigger_name>;
    ...
    

    5) Restore the above dump files once all the “Base” tables found in step #2 are renamed.

    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
    

    Intricacies with above methods : We may need to update the GRANTS for users such that they match the correct schema_name. These could fixed with a simple UPDATE on mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db tables updating the old_schema name to new_schema and calling “Flush privileges;”. Although “method 2″ seems a bit more complicated than the “method 1″, this is totally scriptable. A simple bash script to carry out the above steps in proper sequence, can help you save space and time while renaming database schemas next time.

    The Percona Remote DBA team have written a script called “rename_db” that works in the following way :

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

    To demonstrate the use of this script, used a sample schema “emp”, created test triggers, stored routines on that schema. Will try to rename the database schema using the script, which takes some seconds to complete as opposed to time consuming dump/restore method.

    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               |
    +--------------------+
    

    As you can see in the above output the database schema “emp” was renamed to “emp_test” in less than a second. Lastly, This is the script from Percona that is used above for “method 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
    
    0 讨论(0)
  • 2020-11-22 15:24

    The simplest method is to use HeidiSQL software. It's free and open source. It runs on Windows and on any Linux with Wine (run Windows applications on Linux, BSD, Solaris and Mac OS X).

    To download HeidiSQL, goto http://www.heidisql.com/download.php.

    To download Wine, goto http://www.winehq.org/.

    To rename a database in HeidiSQL, just right click on the database name and select 'Edit'. Then enter a new name and press 'OK'.

    It is so simple.

    0 讨论(0)
  • 2020-11-22 15:24

    In MySQL Administrator do the following:

    1. Under Catalogs, create a new database schema.
    2. Go to Backup and create a backup of the old schema.
    3. Execute backup.
    4. Go to Restore and open the file created in step 3.
    5. Select 'Another Schema' under Target Schema and select the new database schema.
    6. Start Restore.
    7. Verify new schema and, if it looks good, delete the old one.
    0 讨论(0)
  • 2020-11-22 15:26

    You can use SQL to generate an SQL script to transfer each table in your source database to the destination database.

    You must create the destination database before running the script generated from the command.

    You can use either of these two scripts (I originally suggested the former and someone "improved" my answer to use GROUP_CONCAT. Take your pick, but I prefer the original):

    SELECT CONCAT('RENAME TABLE $1.', table_name, ' TO $2.', table_name, '; ')
    FROM information_schema.TABLES 
    WHERE table_schema='$1';
    

    or

    SELECT GROUP_CONCAT('RENAME TABLE $1.', table_name, ' TO $2.', table_name SEPARATOR '; ')
    FROM information_schema.TABLES 
    WHERE table_schema='$1';
    

    ($1 and $2 are source and target respectively)

    This will generate a SQL command that you'll have to then run.

    Note that GROUP_CONCAT has a default length limit that may be exceeded for databases with a large number of tables. You can alter that limit by running SET SESSION group_concat_max_len = 100000000; (or some other large number).

    0 讨论(0)
提交回复
热议问题