Ir al contenido principal

MySQL Latin1 a UTF-8

Existe muchos documentos en Internet de como migrar una base de datos de MySQL con codificación ISO-8859-1 a UTF-8, el hecho de que algún método funcione o no, puede depender de muchos factores.

"Lo mas importante es entender lo que se esta haciendo."

Los factores a tomar en cuenta son.
Apache: Por default entrega las paginas ISO-8859-1 (Latin1)
  • Se puede modificar esto con la variable "AddDefaultCharset UTF-8" en el archivo de configuración de apache default-server.conf o agregando esta variable al archivo .htaccess en el directorio raiz de la aplicacion web.
    • O agregar los encabezados correspondientes a nuestras aplicaciones web.
    1. HTML: <meta charset="utf8">
    2. PHP: header ('Content-type: text/html; charset=utf-8');
    3. PERL: print "Content-Type: text/html; charset=utf-8\n\n";
    En este enlace se puede verificar que codigo de caracteres esta usando nuestra aplicación web.


    MySQL: Revisar si se esta usando el set de caracteres UTF8

    # mysql -u root -p
    mysql> show variables like 'char%';



    Migración de la base de datos vía la consola linux.

    Método 1: En este ejemplo se asume que nuestra base de datos y nuestros datos en si utilizaban una codificación ISO-8859-1 (latin1), aunque se puede dar el caso de que desconozcamos completamente el set de caracteres que se utilizaban.

    Respaldar la base de datos.

    # mysqldump --opt --routines -u root -p --default-character-set=latin1 mibase > mibase_latin1.sql

    Entramos a la consola de MySQL.

    # mysql -u root -p

    Borramos la base de datos.

    mysql> drop database mibase;

    NOTA: Si no podemos usar la base de datos por estar en producción podemos usar cualquier otra base de datos hasta estar seguros de que funciona correctamente nuestra migración.

    Creamos una nueva base de Datos, con el set de caracteres UTF-8.

    mysql> CREATE DATABASE mibase CHARACTER SET utf8 COLLATE utf8_general_ci;

    Desde la linea de comandos convertimos nuestro archivo de respaldo a UTF-8

    # iconv -f ISO-8859-1 -t UTF-8 mibase_latin1.sql > mibase_utf8.sql

    Remplazar la variable CHARSET=latin1 por CHARSET=utf8 dentro del archivo mibase_utf8.sql desde la linea de comandos.

    # perl -pi -w -e 's/CHARSET=latin1/CHARSET=utf8/g;' mibase_utf8.sql

    Con el comando file podemos verificar si el archivo mibase_utf8.sql realmente es un archivo UTF-8.


    Cargamos nuestro archivo UTF-8 a nuestra nueva base de datos.

    # mysql -u root -p --default_character_set utf8 mibase < mibase_utf8.sql

    Entramos en la consola de MySQL y hacemos un volcado de una tabla para ver si los datos son desplegados correctamente.

    # mysql -u root -p

    mysql> use mibase;

    mysql> select * from tarpropiedad;
    ...
    ...
    ...

    Si los acentos se despliegan bien, la migración de la base de datos se puede considerar exitosa.

    En nuestro ejemplo podemos ver que en el volcado de la tabla los acentos no se despliegan correctamente a pesar de haber convertido todo a UTF-8.

    El problema en este caso es que nuestra base de datos si estaba codificada en ISO-8859-1(latin1), pero nuestros datos fueron almacenados en UTF-8, por lo que pasamos al segundo Método.

    Método 2: La base de datos esta configurada en ISO-8859-1(latin1), pero los datos se almacenaron en UTF-8.

    Borramos nuestra nueva base de datos UTF-8 y comenzamos desde el principio.

    # mysql -u root -p

    mysql> drop database mibase;

    Creamos una nueva base de datos, con el set de caracteres UTF-8.

    mysql> CREATE DATABASE mibase CHARACTER SET utf8 COLLATE utf8_general_ci;

    Usamos el mismo archivo de respaldo mibase_latin1.sql

    En esta ocasion no convertimos a UTF8 nuestro archivo de respaldo.

    Solo remplazamos la variable CHARSET=latin1 por CHARSET=utf8 dentro del archivo mibase_latin1.sql desde la linea de comandos.

    # perl -pi -w -e 's/CHARSET=latin1/CHARSET=utf8/g;' mibase_latin1.sql

    Cargamos nuestro archivo de respaldo mibase_latin1.sql a nuestra nueva base de datos.

    # mysql -u root -p --default_character_set utf8 mibase < mibase_latin1.sql

    Entramos nuevamente a la consola de MySQL y hacemos un volcado de una tabla para ver si los datos son desplegados correctamente.

    # mysql -u root -p

    mysql> use mibase;
    mysql> select * from tarpropiedad;
    ...
    ...
    ...

    En este ejemplo podemos ver que los datos son desplegados correctamente.

    Ahora probamos nuestra aplicación para ver el correcto desplegado de datos vía web, al parecer todo esta correcto los acentos se despliegan correctamente.


    Sin embargo al hacer una consulta de una tabla diferente. Los datos están llenos de basura.


    El problema son los campos BLOB, en este ejemplo no convertimos nuestro archivo de respaldo a UTF-8 y los campos BLOB no almacenaron la información en UTF-8 y conservaron la codificación ISO-8859-1(latin1).

    Si tenemos tablas con muchos campos texto que incluyan algún campo BLOB, esto si puede ser un problema serio hay algunos métodos de convertir todos los campos a binarios, pero se necesita estar concentrado en lo que se esta haciendo.

    Aquí hay una liga donde usan este método.

    En mi caso las tablas que usan campos BLOB contienen algunos otros campos pero  son usados para claves o indices y no hay ningún tipo de carácter especial.

    Por lo que puedo convertir cada tabla UTF-8 manualmente.

    Método 3: Este método es la continuación del Método 2, pero solo se convertirán  tablas con campos BLOB a UTF-8.

    Respaldamos nuestra tabla. 

    # mysqldump --opt --routines -u root -p --default-character-set=latin1 mibase tieclientes > tieclientes_latin1.sql

    Desde la linea de comandos convertimos nuestro archivo de respaldo a UTF-8

    # iconv -f ISO-8859-1 -t UTF-8 tieclientes_latin1.sql > tieclientes_utf8.sql

    Remplazar la variable CHARSET=latin1 por CHARSET=utf8 dentro del archivo tieclientes_utf8.sql 

    # perl -pi -w -e 's/CHARSET=latin1/CHARSET=utf8/g;' tieclientes_utf8.sql

    Cargamos nuestro archivo UTF-8 a la base de datos.

    # mysql -u root -p --default-character-set utf8 mibase < tieclientes_utf8.sql
     
    Repetimos el proceso para cada tabla con campos BLOB.

    Nuevamente probamos nuestra aplicación para ver el correcto desplegado de datos vía web, hacemos una consulta a una tabla con campos BLOB.


    En este momento podemos decir que la migración fue un éxito, los acentos se despliegan correctamente.

    En resumen:  

    Cualquier método que encontremos en Internet debe de funcionar solo que al hacer la migración debemos de estar muy atentos para detectar exactamente en que parte, fallo nuestra migración.


    Comentarios