MySQL 从 utf8 切换到 utf8mb4
utf8mb4
幸运的是,MySQL 5.5.3(2010 年初发布)引入了一种名为 utf8mb4
的新编码,它映射到正确的 UTF-8,因此完全支持 Unicode,包括星体符号。
第一步:创建备份
在要升级的服务器上创建所有数据库的备份。 安全第一!
第二步:升级MySQL服务器
将 MySQL 服务器升级到 v5.5.3+,或请服务器管理员为你完成。
第三步:修改数据库、表和列
更改数据库、表和列的字符集和排序规则属性以使用 utf8mb4
而不是 utf8
。
# For each database:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
# For each table:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each column:
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# (Don’t blindly copy-paste this! The exact statement depends on the column type, maximum length, and other properties. The above line is just an example for a `VARCHAR` column.)
由于 utf8mb4
与 utf8
完全向后兼容,因此不应发生 mojibake 或其他形式的数据丢失。 (但你有备份,对吧?)
第四步:检查列和索引键的最大长度
这可能是整个升级过程中最乏味的部分。
从 utf8
转换为 utf8mb4
时,列或索引键的最大长度以字节为单位不变。 因此,它在字符方面更小,因为字符的最大长度现在是四个字节而不是三个。
例如,一个 TINYTEXT
列最多可以容纳 255 个字节,这对应于 85 个三字节字符或 63 个四字节字符。 假设我们有一个使用 utf8 的 TINYTEXT
列,但必须能够包含超过 63 个字符。 鉴于此要求,我们不能将此列转换为 utf8mb4,除非我们还将数据类型更改为更长的类型,例如 TEXT
— 因为如果我们尝试用四字节字符填充它,将只能 输入 63 个字符,但不能更多。
索引键也是如此。 InnoDB
存储引擎的最大索引长度为 767 字节,因此对于 utf8 或 utf8mb4 列,我们最多可以分别索引 255 或 191 个字符。 如果我们当前的 utf8 列的索引长度超过 191 个字符,则在使用 utf8mb4 时需要索引较少的字符。 (因此,我不得不将一些索引 VARCHAR(255)
列更改为 VARCHAR(191)
。)
第五步:修改连接、客户端和服务器字符集
在我们的应用程序代码中,将连接字符集设置为 utf8mb4。 这可以通过简单地将 SET NAMES utf8
的任何变体替换为 SET NAMES utf8mb4
来完成。 如果我们的旧 SET NAMES
语句指定了排序规则,请确保也更改它,例如 SET NAMES utf8 COLLATE utf8_unicode_ci
变成 SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
。
确保同时设置客户端和服务器字符集。 我的 MySQL 配置文件 (/etc/my.cnf) 中有以下内容:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
我们可以轻松确认这些设置是否正常工作:
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)
如我们所见,所有相关选项都设置为 utf8mb4,除了 character_set_filesystem
应该是二进制的,除非我们使用的文件系统支持文件名中的多字节 UTF-8 编码字符,而 character_set_system
始终是 utf8 并且不能被覆盖。
注意
:默认字符集和排序规则也可以在其他一些级别进行配置。
第六步:修复和优化所有表
升级 MySQL 服务器并进行上述必要更改后,确保修复和优化所有数据库和表。 升级后我没有立即执行此操作(我认为没有必要,因为乍一看似乎一切正常),并且遇到了一些奇怪的错误,其中 UPDATE
语句没有任何效果,即使没有 错误被抛出。
我们可以为每个要修复和优化的表运行以下 MySQL 查询:
# For each table
REPAIR TABLE table_name;
OPTIMIZE TABLE table_name;
幸运的是,这可以使用命令行 mysqlcheck
实用程序轻松一次性完成:
$ mysqlcheck -u root -p --auto-repair --optimize --all-databases
这将提示输入 root 用户的密码,之后将修复和优化所有数据库中的所有表。
总结
永远不要在 MySQL 中使用 utf8——总是使用 utf8mb4。 更新数据库和代码可能需要一些时间,但绝对值得付出努力。 为什么要任意限制可以在数据库中使用的符号集? 为什么每次用户输入星体符号作为评论或消息的一部分或我们存储在数据库中的任何内容时,都会丢失数据? 没有理由不在所有地方争取完全的 Unicode
支持。 做正确的事,使用 utf8mb4。 🍻
相关文章
如何在 MySQL 中声明和使用变量
发布时间:2024/03/26 浏览次数:115 分类:MySQL
-
当你需要在 MySQL 中的脚本中存储单个值时,最好的方法是使用变量。变量有不同的种类,有必要知道何时以及如何使用每种类型。
在 MySQL 中使用 Mysqladmin 刷新主机解除阻塞
发布时间:2024/03/26 浏览次数:82 分类:MySQL
-
你将了解阻止主机的原因。此外,通过使用 phpMyAdmin 和命令提示符刷新主机缓存来解除阻塞的不同方法和效果。