什么是 MySQL 中的字符集和排序规则
当 WordPress 在数据库中存储您网站的内容(如文章、标题、已翻译的字符串等)时,它会使用字符集(character set)来表示字符,并使用排序规则(collation)来定义如何比较和排序这些字符。
- 字符集(Charset)
- 定义字符在数据库中的存储方式——本质上就是哪些字节代表哪些字符。
- 排序规则(Collation)
- 定义比较这些字符的规则(例如,是否区分大小写、是否区分重音以及排序顺序)。
为什么这对多语言网站很重要
WPML 支持多语言内容,其中通常包括:
- 特殊字符(如 ñ、é、ö)
- 非拉丁文字(如阿拉伯语、日语、中文、希伯来语)
- 表情符号和符号(🎉、✔️ 等)
其中许多字符需要超过 3 个字节才能正确存储。如果您的数据库使用不兼容的排序规则,字符可能会丢失、被替换为 �,或者引发数据库错误(例如“Incorrect string value”)。
这就是为什么我们强烈建议使用支持 4 字节 Unicode 字符的排序规则。
我们的建议
使用 utf8mb4 字符集和兼容 Unicode 的排序规则,例如:
- utf8mb4_unicode_ci – 兼容性广,是不错的默认选择
- utf8mb4_unicode_520_ci – 在 MySQL 5.6+ 上具有更好的 Unicode 处理能力
- utf8mb4_general_ci – 速度稍快,但 Unicode 比较不够准确
- utf8mb4_bin – 区分大小写和重音(二进制比较)
这些都可以与 WPML 安全配合使用。
重要提示:MySQL 中旧的 utf8 字符集每个字符最多仅支持 3 个字节。它无法处理某些字符(如表情符号或某些表意文字)。请避免将其用于多语言内容。
MySQL 的默认设置是什么
| MySQL 版本 | 默认字符集 | 默认排序规则 | 兼容 Unicode |
|---|---|---|---|
| < 5.5 | latin1 | latin1_swedish_ci | 否 |
| 5.5.x | utf8 | utf8_general_ci | 否 |
| 5.7+ | utf8mb4 | utf8mb4_general_ci / utf8mb4_unicode_ci | 是 |
| 8.0+ | utf8mb4 | utf8mb4_0900_ai_ci | 是 |
WordPress 可能并不总是遵循 MySQL 的默认设置——它可以通过配置或迁移来覆盖默认设置。
为新网站设置字符集和排序规则
为确保 WordPress 使用正确的字符集和排序规则创建新表,请在您的 wp-config.php 中定义以下内容:
define( 'DB_CHARSET', 'utf8mb4' ); // If you have utf8 that's fine, WP will automatically map it as utf8mb4 define( 'DB_COLLATE', 'utf8mb4_unicode_ci' );
这将应用于新安装的网站和新创建的表。
检查现有网站和表的字符集和排序规则
下面介绍了如何检查现有网站上的字符集和排序规则。
选项 1 phpMyAdmin
- 前往您网站的数据库。
- 检查每个表旁边的“Collation”(排序规则)列。
- 单击一个表,查看每一列各自的排序规则。
选项 2 WP-CLI
bash
wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.tables WHERE table_schema = 'your_db_name';"
您还可以检查单个列:
bash
wp db query "SHOW FULL COLUMNS FROM wp_posts;"
如果您看到排序规则以 utf8mb4_ 开头,则说明它已准备好支持所有类型的 Unicode 和 4 字节表意文字。字符集也没有问题。
如果您看到其他内容(例如 utf8_*),则需要对其进行更改。
请注意,每一列的排序规则可能有所不同。
更新现有表和列的字符集和排序规则
在 wp-config.php 文件中更新 DB_CHARSET 和 DB_COLLATE 常量只会影响新表。要将更改应用于现有表和列,您必须使用 SQL 手动转换它们。
我们还建议使用以下命令更新数据库的默认 MySQL 排序规则:
ALTER DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
务必先进行备份
在运行任何转换查询之前:
- 使用 phpMyAdmin 或 mysqldump 导出您的数据库
- 妥善保存,以防出现问题
警告:在严格模式下更新排序规则可能会失败
在更新整个表(或数据库)的排序规则时,MySQL 可能会重建表并重新验证所有列的默认值——包括 DATETIME 等不相关的列。如果您的数据库在严格的 SQL 模式(STRICT_TRANS_TABLES、NO_ZERO_DATE)下运行,具有默认值(如 ‘0000-00-00 00:00:00’)的列将引发错误,例如:
#1067 - Invalid default value.
什么是严格模式
严格模式控制 MySQL 在向数据库中添加或更新数据时如何处理无效或缺失的值。值可能因多种原因而无效。例如,它的数据类型可能与列不匹配,或者可能超出范围。
您可以在 MySQL 文档中找到有关严格模式下不同类型数据验证的信息。
严格模式如何影响 WordPress 网站数据库
默认情况下,WordPress 将 ‘0000-00-00 00:00:00’ 用作某些 datetime 列的默认值,而 NO_ZERO_DATE 严格模式不接受这一值。
请注意,这些默认值在最初创建表时(例如在 WordPress 设置期间)是允许的,但在严格环境下的 ALTER 操作中会失败。
如何检查是否启用了严格模式
运行以下命令:
SELECT @@SESSION.sql_mode, @@GLOBAL.sql_mode;
查找:
- STRICT_TRANS_TABLES
- STRICT_ALL_TABLES
- NO_ZERO_DATE
如果您找到其中任何一项,则说明启用了严格模式。
为避免在更新字符集和排序规则期间出现错误,您只需禁用 NO_ZERO_DATE 严格模式。
如何安全地继续操作
执行以下操作之一以安全地继续:
1. 除非确实需要更改排序规则,否则请避免更改列和表。
2. 在运行转换查询时,仅针对当前会话临时禁用严格模式。您可以使用以下命令执行此操作:
SET SESSION sql_mode = REPLACE(@@sql_mode, 'NO_ZERO_DATE', '');
注意:MySQL 未来计划合并严格模式。
如果出现特定于您数据的其他问题,您可能需要使用以下命令禁用任何严格模式:
SET SESSION sql_mode = '';
用于转换数据的查询
转换整个数据库
以下命令将为您数据库中的每个表生成一个 ALTER TABLE 查询:
SELECT CONCAT( 'ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' ) AS query FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'your_database_name';
在 phpMyAdmin 中运行生成的查询,或者将其复制粘贴到 MySQL CLI / WP-CLI 中。
这可确保您数据库中的所有表都采用新的字符集和排序规则。
转换特定表 可选/辅助
ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
这将更新 wp_posts 表中的所有文本列,以使用 utf8mb4 和指定的排序规则。
转换特定列 可选/辅助
ALTER TABLE wp_posts CHANGE post_title post_title TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意:
- 您必须在 CHANGE 中完全重新声明该列(类型、名称)。
- 确保列类型与现有类型匹配。
转换时的常见错误
以下是您在转换表和列时可能会遇到的两个常见错误。
字符集和排序规则不匹配
-- INVALID: utf8 collation with utf8mb4 charset ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8_general_ci; -- Error: COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'
解决方案:
- 使用匹配的排序规则:utf8mb4_*
索引键长度限制
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
在某些配置中(特别是低于 5.7 的 MySQL 版本),当每个字符增加一个字节时,可能会超出最大索引键长度。
解决方案:
- 如果需要,将编入索引的 VARCHAR(255) 缩短为 VARCHAR(191)
- 或者升级到 MySQL 5.7+ 并确保启用 innodb_large_prefix
总结
- 使用 utf8mb4 字符集以获得全面的 Unicode 支持
- 使用兼容的排序规则:utf8mb4_unicode_ci、utf8mb4_0900_ai_ci 等
- 更新 wp-config.php 以用于新表
- 运行 SQL 迁移以修复现有表
- 切勿混合使用字符集和排序规则——MySQL 会拒绝或破坏它们。