可怕的MySQL导入编码问题 - 重新审视

时间:2011-05-12 21:29:14

标签: mysql sql wordpress character-encoding database-migration

我有标准的MySQL导入编码问题,但我似乎无法解决它。

我的客户端已经运行了一段时间的WordPress安装。我已将数据库转储到文件中,并在本地导入。生成的页面在整个过程中都会出现sp字符。

我已经检查过双方的数据库属性: 制作:show create database wordpress;

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

local:show create database wordpress;

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

production:show create table 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:show create table 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

我花了几个小时阅读关于如何压制 的论坛,但我无法得到任何工作。 99%的答案表示匹配数据库之间的字符集。如果以下内容我认为应该有用:

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

我也使用utf8字符集完成了它。仍然是 's。

我尝试直接修改SQL转储,将 utf8 latin1 放在“SET names UTF8”行中。仍然是 's。

奇怪的症状

我希望这些 字符代替内容中的特殊字符,例如ñö,但我已经看到它通常会出现在哪里只是一个空间。我也看到它取代了撇号(但不是所有撇号),双引号和商标符号。

标记非常罕见。它们每页平均出现三到四次。

通过Sequel Pro(本地或现场)查看数据库时,我看不到任何 。。通过Textmate查看时,我在SQL中看不到任何。。

我错过了什么?

修改

更多信息:

我试图确定实时数据库认为编码是什么。我运行show table status,似乎Collat​​ions是utf8_general_ci, utf8_bin and latin1_swedish_ci`的混合。它们有什么不同?这有关系吗?

我也跑了:show variables like "character_set_database"并获得latin1;

4 个答案:

答案 0 :(得分:11)

这就是我最终解决问题的方法:

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

然后运行此脚本:

$search = array('/latin1/');
$replace = array('utf8');
foreach (range(128, 255) as $dec) {
    $search[] = "/\x".dechex($dec)."/";
    $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);

该脚本查找127以上的所有十六进制字符,并将它们编码到HTML实体中。

然后mysql -uusername -ppassword database < result.sql

答案 1 :(得分:4)

旧版WordPress数据库甚至更新版本的常见问题是数据库表设置为latin-1但内容实际上编码为UTF-8。如果您尝试导出为UTF-8,MySQL将尝试将(假设的)Latin-1数据转换为UTF-8,从而导致双重编码字符,因为数据已经是UTF-8。

解决方案是将表导出为latin-1。由于MySQL认为它们已经是latin-1,它将直接导出。

将字符集从“latin1”更改为“utf8”。 由于转储数据在导出过程中未转换,因此实际上是UTF-8编码数据。

将您的新表创建为UTF-8如果您的CREATE TABLE命令位于SQL转储文件中,请将字符集从“latin1”更改为“utf8”。

正常导入数据。由于你的转储文件中有UTF-8编码数据,转储文件中声明的字符集现在是UTF-8,你导入的表是UTF-8,一切都会顺利进行

答案 2 :(得分:4)

我能够通过修改我的wp-config.php来解决这个问题,如下所示:

/** 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' );

答案 3 :(得分:0)

我认为您可以通过这种方式解决此问题:

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