El temido problema de codificación de importación de MySQL – revisado

5 minutos de lectura

avatar de usuario
Mate

Tengo el problema de codificación de importación de MySQL estándar, pero parece que no puedo resolverlo.

Mi cliente ha tenido una instalación de WordPress funcionando durante algún tiempo. Volqué la base de datos a un archivo y la importé localmente. Las páginas resultantes tienen una salpicadura de caracteres � en todas partes.

Inspeccioné las propiedades de la base de datos en ambos lados: producción: mostrar crear base de datos wordpress;

CREATE DATABASE `wordpress` /*!40100 DEFAULT CHARACTER SET latin1 */

local: mostrar crear base de datos wordpress;

CREATE DATABASE `wordpress` /*!40100 DEFAULT CHARACTER SET latin1 */

producción: mostrar crear tabla wp_posts;

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL auto_increment,
  ...
  KEY `post_date_gmt` (`post_date_gmt`)
) ENGINE=MyISAM AUTO_INCREMENT=7932 DEFAULT CHARSET=utf8

local: mostrar crear tabla wp_posts;

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  ...
  KEY `post_date_gmt` (`post_date_gmt`)
) ENGINE=MyISAM AUTO_INCREMENT=7918 DEFAULT CHARSET=utf8

He pasado horas leyendo foros sobre cómo aplastar el �, pero no puedo hacer que nada funcione. El 99% de las respuestas dicen que coincida el conjunto de caracteres entre las bases de datos. Lo que creo que debería funcionar si lo siguiente:

mysqldump --opt --compress --default-character-set=latin1 -uusername -ppassword wordpress | ssh username@anotherserver.net mysql --default-character-set=latin1 -uusername -ppassword wordpress

Lo he hecho usando el conjunto de caracteres utf8 también. Aún con las �s.

He intentado modificar el volcado de SQL directamente, poniendo con utf8 o latino1 en la línea “SET nombres UTF8”. Aún con las �s.

Síntomas extraños

Esperaría que estos caracteres � aparecieran en lugar de caracteres especiales en el contenido, como norte o o, pero lo he visto donde normalmente habría solo un espacio. También lo he visto en lugar de apóstrofes (pero no todos los apóstrofes), comillas dobles y símbolos de marcas registradas.

Las marcas � son bastante raras. Aparecen en promedio tres o cuatro veces por página.

No veo ningún � cuando veo la base de datos a través de Sequel Pro (localmente o en vivo). No veo ningún � en el SQL cuando lo veo a través de Textmate.

¿Qué me estoy perdiendo?

EDITAR

Más información:

Intenté determinar qué cree la base de datos en vivo que es la codificación. corrí show table statusy parece que las colaciones son una mezcla de utf8_general_ci,utf8_binandlatin1_swedish_ci`. ¿Qué son diferentes? ¿Importa?

También corrí: show variables like "character_set_database" y consiguió latin1;

Así es como terminé resolviendo mi problema:

Primero mysqldump -uusername -ppassword --default-character-set=latin1 database -r dump.sql

Luego ejecute este script:

$search = array('/latin1/');
$replace = array('utf8');
foreach (range(128, 255) as $dec) {
    $search[] = "/\x".dechex($dec)."https://stackoverflow.com/";
    $replace[] = "&#$dec;";
}

$input = fopen('dump.sql', 'r');
$output = fopen('result.sql', 'w');

while (!feof($input)) {
    $line = fgets($input);
    $line = preg_replace($search, $replace, $line);
    fwrite($output, $line);
}

fclose($input);
fclose($output);

El script encuentra todos los caracteres hexadecimales por encima de 127 y los codifica en sus entidades HTML.

Después mysql -uusername -ppassword database < result.sql

  • ¡Muchas gracias, esto resolvió mi problema! He estado trabajando en esta maldita cosa durante dos días. Estaba tratando de obtener una copia de una base de datos que estaba en turco, y tenía caracteres acentuados “especiales”. Cuando lo importé, seguía fallando dondequiera que estuvieran los caracteres especiales. Exporté en el conjunto de caracteres latin1, ejecuté este script anterior y lo importé sin problemas después de eso. Creo que también importé en latin1 charset, ¡pero funcionó! Gracias de nuevo hombre.

    – Joshua Soileau

    6 de agosto de 2013 a las 19:14

Un problema común con las bases de datos de WordPress más antiguas e incluso con las más nuevas es que las tablas de la base de datos se configuran como latin-1 pero los contenidos en realidad están codificados como UTF-8. Si intenta exportar como UTF-8, MySQL intentará convertir los datos (supuestamente) Latin-1 a UTF-8, lo que dará como resultado caracteres codificados doblemente, ya que los datos ya eran UTF-8.

La solución es exportar las tablas como latin-1. Dado que MySQL cree que ya son latin-1, realizará una exportación directa.

Cambie el conjunto de caracteres de ‘latin1’ a ‘utf8’. Dado que los datos descargados no se convirtieron durante el proceso de exportación, en realidad son datos codificados en UTF-8.

Cree su nueva tabla como UTF-8 Si su comando CREAR TABLA está en su archivo de volcado de SQL, cambie el conjunto de caracteres de ‘latin1’ a ‘utf8’.

Importa tus datos normalmente. Dado que tiene datos codificados en UTF-8 en su archivo de volcado, el conjunto de caracteres declarado en el archivo de volcado ahora es UTF-8, y la tabla a la que está importando es UTF-8, todo irá bien.

  • Eso suena exactamente como lo que está sucediendo.

    – Mate

    12 mayo 2011 a las 23:30

  • Intenté el proceso que describiste. La exportación: mysqldump --default-character-set=latin1 -u username -ppassword wordpress > dump-20110512.sql. La importación: mysql -uusername -ppassword wordpress < dump-20110512.utf8-1.sql. Ahora en cualquiera de los campos que contenían una �, se truncan en la primera �. La importación parecía haberse ejecutado sin errores. Cuando reviso el archivo SQL, la declaración INSERT que estoy usando como referencia parece estar completa. Creo que los personajes traviesos todavía están allí. veo el texto donde deberían estar los apóstrofes.

    – Mate

    12 mayo 2011 a las 23:41

  • Cambié cada instancia de latino1 a utf8 en el archivo SQL. Incluyendo algunos al final de CREAR MESA declaraciones, donde tenía: MOTOR=MyISAM AUTO_INCREMENT=635 JUEGO DE CARACTERES POR DEFECTO=latin1;

    – Mate

    12 mayo 2011 a las 23:42


Pude resolver este problema modificando mi wp-config.php de la siguiente manera:

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', 'utf8_general_ci' );

  • Pasé 3 horas buscando una solución. DB volcado y restaurado varias veces sin éxito. ¡Estas 2 constantes me salvaron el día!

    – Julio Vedovatto

    24 mayo 2017 a las 19:38


Creo que puedes solucionar este problema de esta manera:

$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
$db = mysql_select_db('mysql_db', $link);
mysql_query('set names utf8', $link);

¿Ha sido útil esta solución?