MySQL PHP 数据库迁移 UTF-8 问题
MySQL database migration UTF-8 issues with PHP
我正在将我现有的数据库迁移到另一台服务器。为此,我使用 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 的新网络服务器规格(与旧规格相同但服务器不同):
阿帕奇 2.4 PHP 7.0
我怎样才能找回旧的正确编码?为什么 PHP 不再自动正确解码它们?
更新:
使用 mb_detect_encoding
我看到 PHP 在新旧版本中都会检测查询结果中的 ASCII 或 UTF-8,具体取决于是否至少有一个 UTF-8 符号。
问题是在新版本上 PHP 没有正确显示 UTF-8 符号,即使它检测到字符串编码为 UTF-8。
更新 2:
多亏了 我弄清楚了为什么我的条目被破坏了:双重编码 是因为数据库排序规则是 latin1_swedish_ci
而表排序规则是 [=19] =].
这没有回答问题,因为旧网站自动 "translating" 那些损坏的字符,将它们呈现在 HTML 中,我想将这种行为复制到不同的新网站中但具有相同的代码和 php.ini 设置。
我认为您应该检查您的 MariaDB 配置。
首先检查您的 php 代码,以了解是否存在误导性错字(但我认为没有)
其次,检查您的 MariaDB database/tables 结构 [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
兄弟,希望能帮到你解决问题
再见
您是否期待现有数据的变化?不起作用。您需要再次添加数据才能看到更改。从新数据库中删除所有数据并重新添加。
要检查双重编码,使用 SELECT HEX(col)...
é
应该返回 C3A9
(正确的 utf8),但显示 C383C2A9
(双重编码)。
参见:
如果你确实确定你有双重编码,那么修复涉及
UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);
见http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
是的,"double encoding" 是一个无声的 bug -- 两次错误就是一次正确(某种程度上)。
我正在将我现有的数据库迁移到另一台服务器。为此,我使用 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 的新网络服务器规格(与旧规格相同但服务器不同): 阿帕奇 2.4 PHP 7.0
我怎样才能找回旧的正确编码?为什么 PHP 不再自动正确解码它们?
更新:
使用 mb_detect_encoding
我看到 PHP 在新旧版本中都会检测查询结果中的 ASCII 或 UTF-8,具体取决于是否至少有一个 UTF-8 符号。
问题是在新版本上 PHP 没有正确显示 UTF-8 符号,即使它检测到字符串编码为 UTF-8。
更新 2:
多亏了 latin1_swedish_ci
而表排序规则是 [=19] =].
这没有回答问题,因为旧网站自动 "translating" 那些损坏的字符,将它们呈现在 HTML 中,我想将这种行为复制到不同的新网站中但具有相同的代码和 php.ini 设置。
我认为您应该检查您的 MariaDB 配置。
首先检查您的 php 代码,以了解是否存在误导性错字(但我认为没有)
其次,检查您的 MariaDB database/tables 结构 [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
兄弟,希望能帮到你解决问题
再见
您是否期待现有数据的变化?不起作用。您需要再次添加数据才能看到更改。从新数据库中删除所有数据并重新添加。
要检查双重编码,使用 SELECT HEX(col)...
é
应该返回 C3A9
(正确的 utf8),但显示 C383C2A9
(双重编码)。
参见:
如果你确实确定你有双重编码,那么修复涉及
UPDATE tbl SET col = CONVERT(BINARY(CONVERT(col USING latin1)) USING utf8mb4);
见http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases
是的,"double encoding" 是一个无声的 bug -- 两次错误就是一次正确(某种程度上)。