文档首页
MySQL 9.0 参考手册
相关文档 下载此手册

MySQL 9.0 参考手册  /  ...  /  在 3 字节和 4 字节 Unicode 字符集之间转换

12.9.8 在 3 字节和 4 字节 Unicode 字符集之间转换

本节介绍在 utf8mb3utf8mb4 字符集之间转换字符数据时可能会遇到的问题。

注意

此讨论主要集中在 utf8mb3utf8mb4 之间的转换,但类似的原则也适用于在 ucs2 字符集和 utf16utf32 等字符集之间转换。

utf8mb3utf8mb4 字符集的差异如下

  • utf8mb3 仅支持基本多语言平面 (BMP) 中的字符。utf8mb4 还支持位于 BMP 之外的补充字符。

  • utf8mb3 每个字符最多使用 3 个字节。utf8mb4 每个字符最多使用 4 个字节。

注意

此讨论指的是 utf8mb3utf8mb4 字符集名称,以明确区分 3 字节和 4 字节 UTF-8 字符集数据。

utf8mb3 转换为 utf8mb4 的一个优势是,这使应用程序能够使用补充字符。一个权衡是,这可能会增加数据存储空间需求。

就表内容而言,从 utf8mb3 转换为 utf8mb4 没有任何问题

  • 对于 BMP 字符,utf8mb4utf8mb3 具有相同的存储特性:相同的代码值、相同的编码、相同的长度。

  • 对于补充字符,utf8mb4 需要 4 个字节来存储它,而 utf8mb3 根本无法存储该字符。当将 utf8mb3 列转换为 utf8mb4 时,您无需担心转换补充字符,因为不存在补充字符。

就表结构而言,以下是最主要的潜在不兼容性

  • 对于可变长度字符数据类型(VARCHARTEXT 类型),utf8mb4 列的字符最大允许长度小于 utf8mb3 列的字符最大允许长度。

  • 对于所有字符数据类型(CHARVARCHARTEXT 类型),utf8mb4 列的可索引字符最大数量小于 utf8mb3 列的可索引字符最大数量。

因此,要将表从 utf8mb3 转换为 utf8mb4,可能需要更改某些列或索引定义。

可以使用 ALTER TABLE 将表从 utf8mb3 转换为 utf8mb4。假设一个表具有以下定义

CREATE TABLE t1 (
  col1 CHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,
  col2 CHAR(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL
) CHARACTER SET utf8mb3;

以下语句将 t1 转换为使用 utf8mb4

ALTER TABLE t1
  DEFAULT CHARACTER SET utf8mb4,
  MODIFY col1 CHAR(10)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  MODIFY col2 CHAR(10)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;

utf8mb3 转换为 utf8mb4 时需要注意的是,列或索引键的最大长度在 字节 方面保持不变。因此,它在 字符 方面更小,因为字符的最大长度为 4 个字节,而不是 3 个字节。对于 CHARVARCHARTEXT 数据类型,在转换 MySQL 表时,请注意以下问题

  • 检查所有 utf8mb3 列的定义,并确保它们不超过存储引擎的最大长度。

  • 检查所有对 utf8mb3 列的索引,并确保它们不超过存储引擎的最大长度。有时,最大值会因存储引擎增强而发生变化。

如果满足上述条件,您必须缩短列或索引的定义长度,或继续使用 utf8mb3 而不是 utf8mb4

以下是一些可能需要结构更改的示例

  • 一个 TINYTEXT 列可以容纳最多 255 个字节,因此它可以容纳最多 85 个 3 字节或 63 个 4 字节字符。假设您有一个使用 utf8mb3TINYTEXT 列,但必须能够包含超过 63 个字符。除非您还将数据类型更改为更长的类型(如 TEXT),否则您无法将其转换为 utf8mb4

    同样,如果您想将其从 utf8mb3 转换为 utf8mb4,则可能需要将一个非常长的 VARCHAR 列更改为一个更长的 TEXT 类型。

  • 对于使用 COMPACTREDUNDANT 行格式的表,InnoDB 的最大索引长度为 767 个字节,因此对于 utf8mb3utf8mb4 列,您最多可以索引 255 个或 191 个字符,分别。如果您当前有索引长度超过 191 个字符的 utf8mb3 列,则必须索引更少的字符。

    在使用 COMPACTREDUNDANT 行格式的 InnoDB 表中,以下列和索引定义是合法的

    col1 VARCHAR(500) CHARACTER SET utf8mb3, INDEX (col1(255))

    要改为使用 utf8mb4,索引必须更小

    col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))
    注意

    对于使用 COMPRESSEDDYNAMIC 行格式的 InnoDB 表,允许使用超过 767 字节(最多 3072 字节)的 索引键前缀。使用这些行格式创建的表允许您为 utf8mb3utf8mb4 列分别索引最多 1024 或 768 个字符。有关相关信息,请参阅 第 17.21 节“InnoDB 限制”DYNAMIC 行格式

只有在您拥有非常长的列或索引时,才最有可能需要上述类型的更改。否则,您应该能够使用前面描述的 ALTER TABLE 将您的表从 utf8mb3 转换为 utf8mb4,而不会出现问题。

以下项目总结了其他潜在的不兼容性

  • SET NAMES 'utf8mb4' 会导致将 4 字节字符集用于连接字符集。只要没有从服务器发送 4 字节字符,就不应该出现问题。否则,预计每个字符最多接收三个字节的应用程序可能会遇到问题。相反,预计发送 4 字节字符的应用程序必须确保服务器能够理解它们。

  • 对于复制,如果要在源上使用支持补充字符的字符集,则所有副本也必须理解它们。

    此外,请记住以下一般原则:如果表在源和副本上具有不同的定义,这可能会导致意外结果。例如,最大索引键长度的差异使得在源上使用 utf8mb3 并在副本上使用 utf8mb4 存在风险。

如果您已转换为 utf8mb4utf16utf16leutf32,然后决定转换回 utf8mb3ucs2(例如,降级到较旧版本的 MySQL),则以下注意事项适用

  • utf8mb3ucs2 数据应该不会出现问题。

  • 服务器必须足够新才能识别引用您要从中转换的字符集的定义。

  • 对于引用 utf8mb4 字符集的对象定义,您可以在降级之前使用 mysqldump 转储它们,编辑转储文件以将 utf8mb4 的实例更改为 utf8,然后在旧服务器中重新加载该文件,只要数据中没有 4 字节字符。旧服务器在转储文件对象定义中看到 utf8,并创建使用(3 字节)utf8 字符集的新对象。