【问题标题】:MySQL database migration UTF-8 issues with PHP [duplicate]PHP 的 MySQL 数据库迁移 UTF-8 问题
【发布时间】:2018-11-21 23:46:36
【问题描述】:

我正在将现有数据库迁移到另一台服务器。为了实现这一点,我使用 phpMyAdmin SQL 查询导出和导入了数据库。一切正常,除了一些 UTF-8 字符在网站中出现损坏。我使用相同的 PHP 代码获取它们(在不同的服务器上,但具有相同的 PHP 扩展和版本)。

我在新网站和数据库(新旧)上看到的字符串示例(使用 phpMyAdmin):péri-prothétique

我在旧网站péri-prothétique看到的字符串示例

如您所见,PHP 曾经以正确的方式自动对字符进行编码,即使这些字符在数据库中被损坏,但现在不再这样做了(即使我明确地 utf8_encodeutf8_decode 结果也不行)。我什至尝试在每个连接上强制$mysqli->set_charset("UTF8") 无济于事。

Web 服务器、数据库服务器、服务器连接、PHP 和表格都使用 UTF-8 或 utf8mb4 字符集和排序规则,并且设置方式与旧的相同。

我看到的唯一区别是新的数据库服务器是 MariaDB 而不是 MySQL,它的网络服务器是 nginx 而不是 Apache。

来自 phpMyAdmin 的新数据库规格图片:

旧数据库规格图片:

运行网站和 PHP 的新网络服务器规范(与旧的规范相同,但服务器不同): Apache 2.4 PHP 7.0

我怎样才能恢复原来的正确编码?为什么 PHP 不再自动解码它们了?

更新: 使用mb_detect_encoding 我看到新旧版本的 PHP 在查询结果中检测 ASCII 或 UTF-8,这取决于是否至少有一个 UTF-8 符号。 问题是在新版本中,PHP 不会正确显示 UTF-8 符号,即使它检测到字符串编码为 UTF-8。

更新 2: 感谢this question,我弄清楚了为什么我的条目被破坏了:双重编码是因为数据库排序规则是latin1_swedish_ci,而表排序规则是utf8_general_ci。 这并不能回答所想的问题,因为旧网站会自动“翻译”那些损坏的字符,将它们正确呈现在 HTML 中,我想将该行为复制到新网站中,这是一个不同但具有相同代码和php.ini 设置。

【问题讨论】:

  • 不要使用用于 ISO 编码数据的utf8_encode/utf8_decode。除了更改之外,代码完全相同吗?如果查询这两个DB,PHP交互前的数据是否相同?
  • 是的,使用 phpMyAdmin 的查询返回相同的数据。我尝试解码/编码只是为了看看是否会发生什么事情,没有真正的期望
  • MariaDB 10.0.32 比 5.6.39 稍旧,但就本问题而言,它们应该是“相同的”。

标签: php mysql utf-8 utf8mb4


【解决方案1】:

要检查双重编码,使用 SELECT HEX(col)... é 应该会返回 C3A9(正确的 utf8),而是显示 C383C2A9(双重编码)。

见:Trouble with UTF-8 characters; what I see is not what I stored

如果你确实确定你有双重编码,那么修复涉及

UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);

http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases

是的,“双重编码”是一个无声的错误——两个错误就是一个正确(有点)。

【讨论】:

  • 谢谢,我已经看到了您的链接答案,这对我了解导致此问题的原因有很大帮助。但是我不愿意使用您提出的修复程序,因为它将正确编码的 utf8 字符转换为 ? 并且我不能确定我的数据库中没有任何手动控制每条记录(这当然是不可行的) .没有其他方法只针对latin1 编码的字符而不管utf8 字符吗?
  • 如果单独的有不同的问题,您将不得不编写一个程序来推断每一行的状态并对不同的行应用不同的操作。对于个别情况,我也许可以帮助提供诸如CONVERT(...) 之类的表达式。如果您可以通过 SQL 确定哪些 需要修复,请执行 UPDATE ... =CONVERT(...) WHERE ...
  • 另外,请仔细检查我第一个链接中的“最佳实践”。 (听起来你在重建的许多尝试都缺少其中一项。)
【解决方案2】:

我认为您应该检查您的 MariaDB 配置。

首先检查您的 php 代码,以了解是否存在误导性拼写错误(但我认为没有)

其次,检查您的 MariaDB 数据库/表结构 [extracted from here ]:

SELECT * FROM INFORMATION_SCHEMA.SCHEMATA;

第三,检查你的 MariaDB 文件配置(my.cnf)[extracted from here ]:

    [client]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4

然后重启你的服务器:

mysql.server restart

希望它会帮助你解决你的问题兄弟。

再见

【讨论】:

  • 感谢您的快速响应!我修改了 MariaDB 文件配置(从 utf8 到 utf8mb4),但我无法从 ssh 重新启动 mariadb 服务器(不识别“服务”命令)。我会尝试重新启动机器,希望它能正常工作
  • 恐怕它不起作用:(我已经确定第 1 点和第 2 点不是问题(好吧,关于第二点,表格使用 utf8 而不是 utf8mb4,但是旧的)
  • 嗯.. 太糟糕了!我相信你应该搜索你的配置文件或类似的东西.. 带有特殊编码字符的 SQL 插入数据怎么样?它工作正常吗?
  • 在将数据库排序规则更改为 utf8 后(这显然与表排序规则冲突,排序规则不应该级联吗?通过双重编码创建那些损坏的字符)插入在数据库中保持 utf8 兼容记录。关键是旧数据库有那些讨厌的字符,但 PHP 自动将它们“翻译”成 utf8 兼容的字符,我的问题仍然存在:为什么它不再这样做了?
  • SHOW VARIABLES LIKE 'char%'; 你需要 _client、_connection 和 _results 。
【解决方案3】:

您是否期望现有数据发生变化?不起作用。您需要再次添加数据才能看到更改。从新数据库中删除所有数据并重新添加。

【讨论】:

  • 你指的是什么?我没有对数据进行任何更改,只是通过旧数据库中的 SQL 查询复制/粘贴
  • 从新服务器数据库中删除所有数据并从旧服务器数据库备份中恢复。
  • 当然我已经多次这样做了,问题仍然存在。
  • 不能从终端恢复吗?似乎 PHPMyAdmin 没有使用 UTF-8 连接。
  • 我不认为 PHPMyAdmin 应该受到责备。如果您仔细阅读我的问题(我已对其进行了改写以使其更清晰),则两个数据库中的数据是相同的(都带有损坏的双编码字符)。问题似乎是 SELECT 结果在连接或 PHP 端都不会自动解码。
猜你喜欢
  • 2011-06-05
  • 2014-12-18
  • 2017-07-15
  • 2011-02-06
  • 2012-04-11
  • 2023-03-22
  • 1970-01-01
  • 2015-03-10
  • 2011-11-30
相关资源
最近更新 更多