2011-04-07 21 views
7

Estoy ejecutando una aplicación de producción con el servidor de base de datos MySQL. Me olvidé de establecer la intercalación de columnas desde latin hasta utf8_unicode, lo que da como resultado datos extraños al guardar en la columna con datos en varios idiomas.¿Qué pasará con los datos existentes si cambio la intercalación de una columna en MySQL?

Mi pregunta es, ¿qué pasará con mis datos existentes si cambio mi colación a utf8_unicode ahora? ¿Destruirá o dañará los datos existentes o permanecerán los datos, pero los datos nuevos se guardarán como utf8 como debería?

Cambiaré con el cliente web phpMyAdmin.

Respuesta

4

Ejecución de una prueba rápida en MySQL 5.1 con un conjunto de columnas VARCHAR a latin1_bin inserté algunos caracteres no latinos

INSERT INTO Test VALUES ('英國華僑'); 

los selecciono y consigo basura (como se esperaba).

SELECT text from Test; 

da

text 
???? 

luego cambié la intercalación de la columna para utf8_unicode y volver a correr el SELECT y se nota el mismo resultado

text 
???? 

Esto es lo que se esperaría - Mantendrá los datos y los datos seguirán siendo basura, porque cuando se insertaron los datos, la columna perdió la información adicional del carácter y simplemente insertó un? para cada personaje no latino y no hay forma de que el ???? volver a ser 英國 華僑.

Sus datos permanecerán en su lugar pero no serán corregidos.

1

datos válidos estarán debidamente convertidos:

Cuando se cambia un tipo de datos utilizando CHANGE o MODIFY, MySQL intenta valores de las columnas existentes convertirse al nuevo tipo la mejor manera posible. Advertencia: Esta conversión puede dar como resultado alteración de los datos.

http://dev.mysql.com/doc/refman/5.5/en/alter-table.html

... y más específicamente:

Para convertir una columna cadena binaria o no binaria utilizar un conjunto carácter particular, utilice ALTER TABLE. Para conversión exitosa a ocurrir, uno de debe aplicarán las siguientes condiciones: [...] Si la columna tiene una nonbinary tipo de datos (CHAR, VARCHAR, TEXT ), su contenido debe ser codificada en el carácter de columna establecer, no algunos otro conjunto de caracteres. Si el contenido está codificado en un juego de caracteres diferente, puede convertir la columna para usar primero un tipo de datos binarios y luego a una columna no binaria con el juego de caracteres deseado.

http://dev.mysql.com/doc/refman/5.1/en/charset-conversion.html

Así que su problema es datos no válidos, por ejemplo, datos codificados en un conjunto de caracteres diferente. Probé la sugerencia sugerida por la documentación y básicamente arruinó mis datos, pero la razón es que mis datos ya estaban perdidos: la ejecución de SELECT column, HEX(column) FROM table mostró que los caracteres múltiples se habían insertado como 0x3F (es decir, el símbolo ? en Latin1). Mi pila de MySQL había sido lo suficientemente inteligente como para detectar que los datos de entrada no eran Latin1 y convertirlos en algo "compatible". Y una vez que los datos desaparecen, no puede recuperarlos.

Para resumir:

  1. Uso HEX() para averiguar si todavía tiene sus datos.
  2. Realice sus pruebas en una copia de su tabla.
6

El artículo http://mysqldump.azundris.com/archives/60-Handling-character-sets.html analiza esto detenidamente y también muestra lo que sucederá.

Tenga en cuenta que está mezclando un CONJUNTO DE CARACTERES (en realidad una codificación) con una COLECCIÓN.

Un conjunto de caracteres define la representación física de una cadena en bytes en el disco. Puede hacer que esto sea visible, usando la función HEX(), por ejemplo SELECT HEX(str) FROM t WHERE id = 1 para ver cómo MySQL almacena los bytes de su cadena. Lo que MySQL le entrega puede ser diferente, dependiendo del conjunto de caracteres de su conexión, definido con SET NAMES .....

Una clasificación es un criterio de ordenación. Depende del conjunto de caracteres. Por ejemplo, sus datos pueden estar en el conjunto de caracteres latin1, pero pueden ordenarse según cualquiera de los dos ordenamientos alemanes latin1_german1_ci o latin1_german2_ci. Dependiendo de su elección, los diéresis como ö se ordenarán como oe o como o.

Cuando está cambiando un conjunto de caracteres, los datos en su tabla deben ser reescritos. MySQL leerá todos los datos y todos los índices en la tabla, hará una copia oculta de la tabla que temporalmente ocupa espacio en disco, luego moverá la tabla anterior a una ubicación oculta, moverá la tabla oculta a su lugar y luego eliminará los datos anteriores, liberando hasta el espacio en disco. Durante un tiempo intermedio, necesitará dos veces más espacio de almacenamiento para eso.

Cuando está cambiando una intercalación, el orden de clasificación de los datos cambia pero no los datos en sí. Si la columna que está modificando no forma parte de un índice, no es necesario hacer nada aparte de volver a escribir el archivo frm, y las versiones suficientemente recientes de MySQL no deberían hacer más.

Cuando está cambiando una intercalación de una columna que forma parte de un índice, el índice debe reescribirse, ya que un índice es un extracto ordenado de una tabla. Esto volverá a activar la lógica de copia de la tabla ALTER TABLE descrita anteriormente.

MySQL intenta preservar los datos al hacer esto: Siempre que los datos que tenga se puedan representar en el juego de caracteres objetivo, la conversión no tendrá pérdidas. Las advertencias se imprimirán si hay truncamiento de datos en curso, y los datos que no se pueden representar en el juego de caracteres objetivo se reemplazarán por?

0

Mi pregunta es, ¿qué pasará con mis datos existentes si cambio mi coordenada a utf8_unicode ahora?

Respuesta: Si cambia a utf8_unicode_ci, no pasará nada con sus datos existentes (que ya están dañados y permanecen dañados hasta que los modifique).

¿Va a destruir o dañar los datos existentes o se mantendrán los datos, pero los nuevos datos serán guardados como UTF-8 como debería?

Respuesta: Después de cambiar a utf8_unicode_ci, los datos existentes no se destruirán. Seguirá siendo el mismo que antes (algo así como ????). Sin embargo, si inserta datos nuevos que contienen caracteres Unicode, se almacenarán correctamente.

Cambiaré con el cliente web phpMyAdmin.

Respuesta: Claro, usted puede cambiar el cotejo con phpMyAdmin yendo a Operaciones> Opciones de tabla

0

PRECAUCIÓN! Algunos problemas se resuelven a través de

ALTER TABLE ... CONVERT TO ... 

Algunos se resuelven a través de un proceso de 2 pasos

ALTER TABLE ... MODIFY ... VARBINARY... 
ALTER TABLE ... MODIFY ... VARCHAR... 

Si lo hace el mal, que tendrá una peor desastre!

  1. Haz SELECT HEX(col), col ... para ver lo que realmente tienes.
  2. Estudio de esto para ver qué caso tiene: Trouble with utf8 characters; what I see is not what I stored
  3. Realizar la solución correcta, basado en estos casos: http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
Cuestiones relacionadas