【问题标题】:Encoding mixes up after replication复制后编码混淆
【发布时间】:2015-04-05 16:11:41
【问题描述】:

我有两个 MySql 数据库,在不同的服务器上。

我正在将内容从 DATABASE 1 复制到 DATABASE 2。

数据库 1

包含 UTF8_unicode_ci 中的所有内容
通过 php 连接是用set_charset(utf8)

数据库 2

同1

复制:

我正在将内容从 DATABASE 1 复制到 DATABASE 2,如下所示:

内容打印在文件 JSONfile.php 中,带有 header('Content-type: application/json; charset=utf-8') 和 php json_encode()

使用file_get_contents(JSONfile.php) 和`json_decode()` 通过php 获取内容。

然后保存到DATABASE 2

旁注:我没有其他方法可以在我正在使用的服务器上复制内容。不允许远程连接。

问题:

当我从 DATABASE 2 检索数据并显示它们(总是使用元字符集 utf8)时,似乎出现了一些奇怪的符号,如下所示:

... autorizar la restauración de la pintura âLa Inmaculadaâ de Fran ...

注意:mb_detect_encoding() 在此字符串上返回:UTF-8

只是为了尝试,我做了utf8_decode(),它进入了:

... la restauración de la pintura “La Inmaculada” de ...

它修复了一些问题并将奇怪与非奇怪混合在一起。

那么,一定是某处出错了。

有什么办法找出错误吗?

编辑:- DATABASE 1 中的内容来源-

DATABASE 1 中的所有内容都是在不同网站上 SCRAPE 的结果。
所有刮擦均已使用 html 元字符集 utf8 打开网站。
一些来源有 &Xacute;实体,有些则没有。

编辑 2:

在数据库 1

上转换为十六进制

Después de dos --> 4465737075c3a97320646520646f73

在数据库 2

上转换为十六进制

Después de dos --> 4465737075c3a97320646520646f73 (同上)

所以问题不在于从一个数据库复制到另一个。

我一直在调查,有一件非常奇怪的事情。在数据库(两者)上,当我通过 phpMyAdmin 访问时,有些字段显示正确,例如“camión”。但是在有问题的字段上显示编码,例如:Después

我不知道 phpMyAdmin 应该显示 utf8 形式还是人类可读的形式。但是同一张表的字段之间的这种差异肯定是找到问题的大门。

显示创建表返回:

CREATE TABLE `contents_data` (
`id` bigint(20) unsigned NOT NULL,
 `title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
 `main_img` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
 `data` text COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`),
 CONSTRAINT `ContentsDataIdFK` FOREIGN KEY (`id`) REFERENCES `contents` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

编辑

对带有字符串“Alcázar”的字段执行 col(HEX) 会返回“416c63e17a6172”

非常好奇的事情:

在上面显示的表格中,字段 VARCHAR 对重音进行了正确编码,而字段 TEXT 在所有行中都造成了麻烦!

列是:“VARCHAR”和“TEXT”(请参阅上面的 CREATE TABLE 代码)

注意:每一行都会发生同样的事情,无论刮擦的来源。

【问题讨论】:

  • html 实体ó 不受 MySQL 中任何东西的影响,因此我们可以忽略这种情况。除了数据库不一致,无法搜索(WHERE,GROUP BY,ORDER BY),应该没有问题。我假设scrap 应该拼写为scrape?
  • @RickJames - 将废品更新到废品(对不起,错误,谢谢。) - 我再次编辑了问题以显示有关此案的更多有用信息。我还在研究它。非常感谢您花时间阅读我。我真诚地欣赏它。
  • 请SELECT col, HEX(col) ... 处理“camión”案例。如果您在单个表中有一个列,其中有一些 ó 和一些 é,则它不容易修复。
  • @RickJames 再次编辑问题。现在将阅读您对下面案例 1 的编辑。关于字符集/整理的好文章。我会说的圣经。和平。
  • @RickJames 我添加了一张图片(PHPmyAdmin 的屏幕截图),以说明我的意思。哪个字段的行为错误?一个显示人类结果可读的口音,还是一个显示 utf8 编码的口音?

标签: php mysql database utf-8 character-encoding


【解决方案1】:

当您将 set_charset 设置为(或默认为)latin1 并且该列的定义为 CHARACTER SET latin1 时,您可能存储了该“o-acute”。

案例 1 这将 C3B3(用于 o-acute 的 utf8 十六进制)变成了 Ã(在 latin1 中为十六进制 C3)和 ³(在 latin1 中为 B3)。

SELECT col, HEX(col) ... 看看现在有什么。也可以通过SHOW CREATE TABLE 获取CHARACTER SET。

(编辑)在这种情况下仅,执行2-step ALTER,类似于

ALTER TABLE Tbl MODIFY COLUMN col VARBINARY(...) ...;
ALTER TABLE Tbl MODIFY COLUMN col VARCHAR(...) ... CHARACTER SET utf8 ...;

长度足够大,而其他 ... 的其他内容(NULL 等)已经在列中。

同样,TEXT -> BLOB -> TEXT。

如果col 在任何索引中,您可能希望DROP INDEX 在第一个ALTER 和ADD INDEX 在第二个。 (这是为了提高效率,也可能是为了避免索引限制。)

案例 2 或者它可能是“双重编码”——HEX 不会是 C3B3,而是更长的。

一旦确定是哪种情况,我们就可以讨论如何处理。

Blog with further discussion.

【讨论】:

  • 感谢您抽出宝贵的时间,认真的。我编辑了我的问题以解释来源的来源,所以假设是第一种情况,但并非总是如此。你我做什么?再次感谢。
  • 我为案例 1 添加了详细信息。
  • 那么,既然字段 TEXT 给了所有麻烦,并且字段 VARCHAR 在所有行中都可以正常工作,我应该执行 TEXT->BLOB->TEXT,还是有其他方法可以解决它?
  • 是的,听起来您应该只在 TEXT 字段上执行两步 ALTER。根据您的编辑,也许 VARCHAR 可以保持原样(即使它是 latin1)。
  • 那是西班牙语,对吗?请记住,latin1 不会让您越过西欧。
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-17
  • 2013-07-06
  • 1970-01-01
  • 2015-12-09
  • 2013-01-29
相关资源
最近更新 更多