2010-10-03 12 views
8

No estoy 100% seguro en los detalles, entonces me encantaría que alguien me aclare, pero seguiré adelante con lo que creo que está pasando ...Rails, MySQL, datos Unicode y tablas latin1 - ¿A dónde ir desde aquí?

Cuando configuré por primera vez mi base de datos, Utilicé la codificación de caracteres predeterminada del sistema sin pensarlo, y era latin1. Nunca pensé en i18n/l10n. Simplemente no se me ocurrió. Acabo de aceptar los valores predeterminados y fui con eso.

De todos modos, he estado utilizando la base de datos exclusivamente para una aplicación de Rails, y ahora tenemos varios GB de datos, 100.000 de filas y muchos usuarios internacionales. Me he dado cuenta de que muchos de nuestros usuarios extranjeros están insertando datos que parecen ser Unicode/non-latin1. Aquí hay un ejemplo:

¿Qué hay de las cosas locas de Unicode? ☢ ☠ ☭

database.yml

Aquí está nuestro archivo database.yml.

development: 
    adapter: mysql 
    database: XXX 
    username: YYY 
    password: ZZZ 
    host: localhost 
    encoding: utf8 

Como puede ver, estamos configurando la codificación de caracteres para utf8. Sin embargo, todas nuestras tablas tienen un juego de caracteres predeterminado de latin1. Estoy seguro de esto.

Actualización Después de mirar de cerca, nuestra producción database.yml no especifica una codificación, mientras que mi copia local especificaba utf8. Esto causaba problemas cuando volcaba la base de datos de producción y la importaba localmente. Parece que ahora la importación funcionaba bien, pero Rails estaba leyéndola incorrectamente.

herramienta MySQL CLI

Cuando veo los datos a través de la herramienta MySQL CLI, que muestra todos los caracteres Unicode correctamente. Sin embargo, la declaración 'show create table' muestra claramente que las tablas son charset por defecto latin1. Esto me lleva a creer que MySQL es de alguna manera lo suficientemente inteligente como para almacenar datos que no sean latin1.

cabecera HTTP

Nuestra cabecera HTTP Content-Type se establece en UTF-8, así:

Content-Type: text/html; charset=utf-8 

Conversión intentos

He jugado un poco con convirtiendo nuestras tablas en codificación utf-8, todo sin éxito. Principalmente traté de volcar la base de datos, ejecutando iconv para convertir y luego volver a importar con las tablas establecidas en utf-8. MySQL no tenía errores, pero todos los datos de Unicode estaban distorsionados.

¿Qué hacer?

Estoy algo atrapado en cuanto a qué hacer (en todo caso). Creo firmemente en no arreglar lo que no se rompe, pero toda esta situación me preocupa. Nunca hemos tenido quejas de los usuarios sobre no poder almacenar sus datos, y todo parece estar funcionando bien. Me gustaría saber qué está sucediendo exactamente, quién/qué está haciendo la conversión (¿MySQL? ¿Ruby? Rails? ¿Conexión MySQL?), Y cualquier consejo sobre cómo proceder.

Respuesta

3

Lo más probable es que los datos almacenados en sus tablas sean UTF-8 válidos, pero MySQL cree que es Latin-1 (porque ese es el tipo de datos con el que se declaró la columna). También es válido Latin-1, por supuesto, ya que AFAIK cualquier secuencia arbitraria de bytes es válida Latin-1.

Lo que sucede cuando se convierte a UTF-8 es que MySQL ve datos codificados Latin-1 válidos y los convierte en el equivalente UTF-8 válido. Esto significa que usted obtiene datos codificados en doble UTF-8, razón por la cual está distorsionado.

La forma de evitar esto es convertir la columna en una cadena binaria y luego en UTF-8 desde allí. MySQL no convierte la cadena cuando haces esto (porque la estás convirtiendo a través de un formato que solo dice "trata esta cadena como una serie de 0 y 1").

ALTER TABLE MyTable 
    MODIFY MyColumn CHAR(100) CHARACTER SET binary, 
    MODIFY MyColumn CHAR(100) CHARACTER SET utf8 
+1

He jugado un poco con la modificación binaria, también, y demora tanto. Creo que voy a volcar toda la base de datos (mysqldump) y luego cambiar los valores predeterminados de la tabla a utf8 en el volcado de SQL, y luego volver a importar. Creo * que debería funcionar, ya que MySQL no hará ninguna conversión en ese caso, solo tome los datos normalmente. – Micah

+0

¿Funcionó una reimportación, @Micah? – webDEVILopers

+0

Éste resolvió todos mis problemas, @Micah: http://www.whitesmith.co/blog/latin1-to-utf8/ – webDEVILopers

0

Lo que funcionó para mí (y otros) era utilizar el adaptador mysql2.

En su Gemfile:

gem "mysql2"

En config/database.yml:

adapter: mysql2

Y, usted debe recordar para establecer su base de datos de carácter establece en UTF -8 también, pero según tengo entendido, también lo hizo :-)

Espero que esto ayude?

Cuestiones relacionadas