php - PHP 的 MySQL 数据库迁移 UTF-8 问题

标签 php mysql utf-8 utf8mb4

我正在将现有数据库迁移到另一台服务器。为了实现这一点,我使用 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 的新数据库规范图片:

IMAGE

旧数据库规范图片:

IMAGE

网站和 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/

相关文章:

PHP,限制用户输入错误值x次

javascript - 上传时验证图片确实是身份证件或护照文件

php - 如何存储有关表的元数据?

php - 如何在酒店预订系统中实现查询空房情况

php - 我如何在 PHP 中的另一个数组中转换这个 M-N mysql 数组? (里面的例子)

mysql - 无法在 WordPress 中使用 wpdb->insert 查询插入数据库

sql - 如何在 MYSQL 查询中将名字和姓氏作为全名?

ruby-on-rails - Encoding::UndefinedConversionError -ASCII-8BIT to UTF-8 ruby​​ on rails

通过ftp下载PHP文件,考虑到utf8如何做到这一点?