Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Converting Between 3-Byte and 4-Byte Unicode Character Sets

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

本节描述了在utf8mb3utf8mb4字符集之间可能遇到的问题。

Note

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

utf8mb3utf8mb4字符集的区别在于:

  • utf8mb3只支持基本多语言平面(BMP)中的字符。utf8mb4还支持超出BMP范围的补充字符。

  • utf8mb3每个字符最多使用三个字节。utf8mb4每个字符最多使用四个字节。

Note

本讨论中,utf8mb3utf8mb4字符集名称用于明确地指代3字节和4字节UTF-8字符集数据。

utf8mb3转换到utf8mb4的优点是可以使用补充字符。一个tradeoff是这可能增加数据存储空间要求。

在表内容方面,utf8mb3转换到utf8mb4没有问题:

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

  • 对于补充字符,utf8mb4 需要四个字节来存储,而 utf8mb3 无法存储该字符。在将 utf8mb3 列转换为 utf8mb4 时,不需要担心补充字符的转换,因为没有。

从表结构角度看,这些是主要的不兼容性:

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

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

因此,转换表格从 utf8mb3utf8mb4 可能需要更改一些列或索引定义。

可以使用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;

utf8mb3utf8mb4时,需要注意的是,在字节方面列或索引键的最大长度保持不变,但是在字符方面则变小,因为每个字符的最大长度由四个字节改为三个。对于CHARVARCHARTEXT数据类型,转换 MySQL 表时需要注意以下问题:

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

  • 检查所有utf8mb3列上的索引,确保它们不超过存储引擎的最大长度。有时由于存储引擎的改进,最大长度也可能会改变。

如果前提条件适用,您必须么减少列或索引的定义长度,或者继续使用utf8mb3而不是utf8mb4.

以下是一些可能需要结构变化的地方:

  • TINYTEXT 列可以存储最多255字节,所以它可以存储最多85个3字节或63个4字节的字符。假设你有一个使用 utf8mb3TINYTEXT 列,想要容纳更多于63个字符。你不能将其转换为 utf8mb4,除非你也更改数据类型到一个更长的类型,如TEXT

    类似地,如果你有一个非常长的VARCHAR 列,想要从 utf8mb3 转换到 utf8mb4,你可能需要将其更改为一个更长的TEXT 类型。

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

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

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

    要使用 utf8mb4,索引必须更小:

    col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))
    Note

    对于使用 COMPRESSEDDYNAMIC 行格式的 InnoDB 表,索引前缀 长度最多为 767 字节(至多 3072 字节)。使用这些行格式的表可以对 utf8mb3utf8mb4 列进行索引,最大支持 1024 或 768 个字符。有关相关信息,请参阅第17.21节,“InnoDB Limits”DYNAMIC Row Format

前述类型的更改最可能只在您有非常长的列或索引时才需要。否则,您可以使用ALTER TABLE,按照之前描述的方式将表从 utf8mb3 转换到 utf8mb4 无需问题。

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

  • SET NAMES 'utf8mb4' 将连接字符集使用 4 字节字符集。只要服务器中没有发送 4 字节字符,应用程序就不会出现问题。否则,期望每个字符最多 3 个字节的应用程序可能会出现问题。反之,期望发送 4 字节字符的应用程序必须确保服务器理解它们。

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

    另外,需要注意的一般原则是,如果源端和副本端表定义不同,这可能会导致意外结果。例如,索引键长度的差异使得在源端使用 utf8mb3,在副本端使用 utf8mb4 是风险很高的选择。

如果您已经转换到 utf8mb4utf16utf16leutf32,然后决定转换回 utf8mb3ucs2(例如,降级到 MySQL 旧版本),这些考虑因素适用:

  • utf8mb3ucs2 数据不会出现问题。

  • 服务器必须足够新版本,以便识别您要转换的字符集定义。

  • 对于引用utf8mb4字符集的对象定义,可以使用mysqldump在降级前 Dump它们,编辑 dump 文件将utf8mb4替换为utf8,然后在老服务器中重新加载文件,只要数据中没有 4 字节字符。老服务器在 dump 文件中看到utf8对象定义,创建新的对象使用 (3 字节) utf8 字符集。