Jun 112014
 
Artículo MySQL

Casi con toda seguridad, lo primero que se le ocurrirá a un DBA para cambiar el nombre de una base de datos es usar un comando de la forma "RENAME DATABASE nombre_viejo TO nombre_nuevo", pero desafortunadamente, este comando no existe en MySQL.

En este artículo explicamos las alternativas existentes para realizar esta tarea.

1. Volcar la base de datos y recuperar el volcado sobre la nueva base de datos

Si la base de datos es pequeña, esta puede ser la manera más rápida y sencilla de cambiar su nombre:

  • Volcar la base de datos. Suponiendo que la base de datos existente se llama “nombre_viejo”, ejecutamos el siguiente comando en un terminal:
    $ mysqldump nombre_viejo > nombre_viejo.dmp

    Si la base de datos contiene triggers, funciones o procedimientos almacenados, es necesario también volcarlos a un fichero:

    $ mysqldump nombre_viejo -d -t -R -E > stored_routines_triggers_events.out
  • Crear la nueva base de datos. Nos conectamos a mysql, y ejecutamos el comando para crear una base de datos llamada “nombre_nuevo”:
    mysql> CREATE DATABASE nombre_nuevo;
  • Importar el volcado en la nueva base de datos. Desde línea de comandos llamamos al intérprete mysql para que importe, en la base de datos “nombre_nuevo”, el fichero generado previamente:
    $ mysql nombre_nuevo < nombre_viejo.dmp
  • Eliminar la vieja base de datos. Ya solo nos queda eliminar la antigua base de datos. Nos conectamos a mysql, y ejecutamos:
    mysql> DROP DATABASE nombre_viejo;

2. Mover cada una de las tablas a la nueva base de datos

Si el tamaño de la base de datos es grande, y el sistema tiene poco espacio de disco libre, puede que no sea posible realizar el volcado y crear la nueva base de datos siguiendo el procedimiento presentado en el apartado anterior.

En este caso, la alternativa es crear la nueva base de datos, y mover a la misma cada una de las tablas de la base de datos vieja. El comando “RENAME TABLE” se puede utilizar para este propósito (de la misma manera que el comando “mv” en un sistema Linux nos permite cambiar un fichero de un directorio a otro).

Los pasos a seguir son:

  • Crear la nueva base de datos
mysql> CREATE DATABASE nombre_nuevo;
  • Obtener un listado de las tablas existentes en la vieja base de datos
mysql> USE nombre_viejo;
Database changed
mysql> SHOW TABLES;
+---------------------------+
| Tables_in_nombre_viejo    |
+---------------------------+
| clientes                  |
| productos                 |
| pedidos                   |
...
  • Para cada tabla, moverla a la nueva base de datos
mysql> RENAME TABLE clientes TO nombre_nuevo.clientes;
mysql> RENAME TABLE productos TO nombre_nuevo.productos;
mysql> RENAME TABLE pedidos TO nombre_nuevo.pedidos;
  • Eliminar la vieja base de datos
mysql> DROP DATABASE nombre_viejo;

Nota: En lugar de obtener los nombres de las tablas con el comando “show tables”, podemos ejecutar un comando que genera directamente los comandos “RENAME TABLE” a ejecutar:

mysql> SELECT CONCAT('RENAME TABLE ',table_schema,'.',table_name,
                     ' TO ','nombre_nuevo.',table_name,';')
    FROM information_schema.TABLES
    WHERE table_schema LIKE 'nombre_viejo';

3. Cambiar el nombre del directorio que contiene la base de datos

Este procedimiento sólo se puede aplicar si todas las tablas de la base de datos son de tipo MyISAM.

Por otra parte, hay que realizarlo habiendo parado completamente la base de datos.

Si se cumplen estos requisitos, el procedimiento a seguir es:

  • Parar el servicio mysql.
    Típicamente, en un sistema Linux podemos hacer esto con un comando:
$ /etc/init.d/mysql stop
  • Cambiar de nombre el directorio que contiene la base de datos.
    En una instalación estándar de MySQL sobre un sistema Linux, los directorios que contienen las bases de datos se encuentran bajo “/var/lib/mysql”:
$ cd /var/lib/mysql
$ mv nombre_viejo nombre_nuevo
  • Arrancar de nuevo el servicio mysql
$ /etc/init.d/mysql start

Script para cambiar de nombre una base de datos mysql

Todos los pasos explicados en el segundo apartado se pueden automatizar mediante un script “rename_db”, como el que fué publicado en el blog de Percona:

#!/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

Nota: Como se puede ver, en las llamadas a mysql y mysqldump que contiene el script no se especifican el usuario y la contraseña para acceder a la base de datos. El script asume que éstos están configurados en un fichero ~/my.cnf (my.ini), o bien que se pasan como variables de entorno.

 Publicado por en 7:20 pm

 Deja un comentario

(requerido)

(requerido)