导入 sql 文件时出现 UTF-8 编码问题

UTF-8 encoding problem while importing a sql file

我有一个服务器托管 MySQL,PHPMyAdmin 报告:

Server version: 5.1.56-community
MySQL charset: UTF-8 Unicode (utf8)

我使用 mysqldump -uroot -p database > file.dumpmysqldump -uroot -p database -r file.dump 导出了 sql(无论如何生成的文件都是相同的)。

在本地,我安装了 MySQL 5.5 和 HeidiSQL 9.5。

因为服务器的 SQL 文件 my.ini 有:

default-character-set=utf8

我把本地my.ini文件改成了

default-character-set=utf8

还有:

character-set-server=utf8

它们都设置为 latin1。不知道为什么我在这里设置了 character-set-server 而服务器没有。无论如何。

现在我启动 HeidiSQL,它显示 utf8mb4 个引用而不是 utf8 个会话参数。不知道为什么:

现在,我导入了我的转储文件,我发现即使在 utf8 中显然配置了所有内容,但我似乎遇到了一些编码问题。

在服务器上,我看到:

在本地,在海蒂SQL,我看到:

à 这样的特殊字符在本地数据库中显示不正确。

我是不是做错了什么?

请注意,如果我在服务器上安装 HeidiSQL,变量选项卡会显示 SessionGlobal[=63 的相同值=] 参数,并且 à 正确显示。

所以这可能是问题的根本原因,但我不知道如何解决。如果我在导入 sql 文件之前更改 Session 值,它不会解决问题,而且当我启动 Heidi[=71] 时,值又回到 utf8mb4 =] 再次。

一些想法:

看来您的字符集设置正确。 HeidiSQL显示不同字符集的事实,可能是因为客户端自己设置了字符集。

例如,您的 mysql 服务器可能默认使用 "Character set A"。如果客户端连接并说他们想要 "Character set B",服务器将即时转换它。

utf8mb4 是一个超集(并且优于)utf8。最好让您的服务器默认为 utf8mb4utf8mb4 的流行用例是表情符号。

无论如何,您得到 mojibake 的原因可能与正确设置这些字符集无关。

我认为可能发生的事情如下(这是猜测)。

  1. 您的 tables/columns 被设置为 UTF-8。
  2. 客户端连接并告诉服务器"I want to use ISO-8559-1/latin instead"。
  3. 服务器愉快地遵守并将客户端 ISO-8559-1 字符串即时转换为 UTF-8。
  4. 尽管客户端想要使用 ISO-8559-1,但它实际上 发送 UTF-8。
  5. 服务器认为数据是 ISO-8559-1 并以此对待它,并将使用 ISO-8559-1 的 UTF-8 转换为 UTF。它实际上是双重编码。

如果我是对的,这意味着您可以将所有列、连接和 table 设置为 UTF-8,但您的数据很糟糕。

如果这是正确的,这个过程是可逆的

你真的只需要相反的操作。例如,如果您有一个 PHP 字符串 $data,它是 'double-encoded' 作为 UTF-8,该过程将简单地调用它:

$output = utf8_decode($input)

也可以在 MySQL 中修复此问题。看到这个 stack overflow question.

需要注意的几点:

  1. 确保确实如此。执行此操作后得到正确的输出吗?
  2. 显然要备份。
  3. 还要绝对确保将双编码 UTF-8 写入数据库的问题现已修复。您最不想要的是 table,它是不同编码的混合体。

旁注:这个问题非常普遍。你是法国人有点幸运,因为它突出了问题。我见过的许多英文系统都有这个问题,但它在很长一段时间内基本上都没有引起注意,因为很多文本都没有超出常见的 ASCII 范围。

感谢 deceze 评论,我可以解决这个问题。

在 HeidiSQL 中,当我选择 sql 文件执行时,实际上有一个 "ncoding" 选项,我原来没有注意到 ;-)

如果我保留 "auto-detect",导入会生成错误内容(带有 mojibake 字符)

如果我强制"UTF-8",导入是完美的

不知道为什么 HeidiSQL 无法自动检测编码...

你有 "Mojibake"。 à变成Ã(有两个字符,第二个是一个space)。

这是由于过程中某处涉及 latin1 造成的。 SESSIONGLOBAL 设置没有错误。让我们看看SHOW CREATE TABLE

有关可能的原因,请参阅 中的 Mojibake。可能涉及"Double Encoding";让我们看看 SELECT col, HEX(col) ....

至于修复数据--这取决于你是简单的Mojibake还是Double Encoding。两者见 http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases