我正在将现有数据库迁移到另一台服务器。为了实现这一点,我使用 phpMyAdmin SQL 查询导出和导入数据库。一切工作正常,只是网站中某些 UTF-8 字符出现损坏。我使用相同的 PHP 代码获取它们(在不同的服务器上,但具有相同的 PHP 扩展和版本)。
我在新网站和数据库(新旧)上看到的字符串示例(使用 phpMyAdmin):péri-prothétique
我在旧网站中看到的字符串示例 péri-prothétique
正如你所看到的,PHP 过去常常以正确的方式自动编码字符,即使字符在数据库中被破坏,但现在不再这样做了(即使我明确地 utf8_encode
或 utf8_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 设置。
最佳答案
要检查双重编码,请使用 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
是的,“双重编码”是一个无声的错误——两个错误构成一个正确(某种程度上)。
关于php - PHP 的 MySQL 数据库迁移 UTF-8 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50819527/