Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 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 的一个优点是,这使应用程序能够使用补充字符。一个权衡是,这可能会增加数据存储空间的需求。

在表内容方面,从 utf8mb3 转换到 utf8mb4 不会出现问题:

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

  • 对于补充字符,utf8mb4 需要四个字节来存储它,而 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 时需要注意的是,列或索引键的最大长度以字节为单位保持不变。因此,以字符为单位的最大长度变小,因为每个字符的最大长度从 3 字节变为 4 字节。对于 CHARVARCHARTEXT 数据类型,在转换 MySQL 表时需要注意以下问题:

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

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

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

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

  • 一个 TINYTEXT 列最多可以容纳 255 字节,因此可以容纳最多 85 个 3 字节字符或 63 个 4 字节字符。假设您有一个使用 utf8mb3 的 TINYTEXT 列,但需要容纳超过 63 个字符。除非您也将数据类型更改为较长的类型,例如 TEXT,否则无法将其转换为 utf8mb4。

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

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

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

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

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

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

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

前面的更改可能只需要在您拥有非常长的列或索引时进行。否则,您应该能够将表从 utf8mb3 转换为 utf8mb4,无需问题,使用 ALTER TABLE,如前所述。

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

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

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

    此外,请牢记一个通用的原则:如果源服务器和副本服务器上的表定义不同,这可能会导致意外的结果。例如,最大索引键长度的差异使得在源服务器上使用 utf8mb3 而在副本服务器上使用 utf8mb4 是有风险的。

如果您已经转换为 utf8mb4utf16utf16leutf32,然后决定转换回 utf8mb3ucs2(例如,降级到旧版本的 MySQL),以下几点需要注意:

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

  • 服务器必须足够新,以便识别从中转换的字符集的定义。

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