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

本节介绍了在utf8mb3utf8mb4字符集。

笔记

这个讨论主要集中在之间的转换utf8mb3utf8mb4, 但类似的原则适用于在ucs2字符集和字符集如utf16要么utf32.

utf8mb3utf8mb4字符集的区别如下:

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

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

笔记

本次讨论是指utf8mb3utf8mb4要明确引用 3 字节和 4 字节 UTF-8 字符集数据的字符集名称。例外是在表定义中,utf8使用,因为 MySQL 转换实例utf8mb3在此类定义中指定utf8,这是一个别名utf8mb3.

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

在表格内容方面,从utf8mb3utf8mb4没有问题:

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

  • 对于一个补充字符,utf8mb4需要四个字节来存储它,而utf8mb3根本无法存储角色。转换时utf8mb3列到utf8mb4,您不必担心转换补充字符,因为没有。

    在表结构方面,这些是主要的潜在不兼容性:

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

  • 对于所有字符数据类型 (字符,VARCHAR, 和文本types),可以索引的最大字符数更少utf8mb4列比utf8mb3列。

    因此,要将表从utf8mb3utf8mb4,可能需要更改某些列或索引定义。

    表格可以从utf8mb3utf8mb4通过使用更改表.假设一个表有这个定义:

CREATE TABLE t1 (
  col1 CHAR(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  col2 CHAR(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
) CHARACTER SET utf8;

以下语句转换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是列或索引键的最大长度在以下方面没有变化字节.因此,它在以下方面更小人物因为一个字符的最大长度是四个字节而不是三个。为了字符,VARCHAR, 和文本数据类型,在转换 MySQL 表时注意这些问题:

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

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

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

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

  • 一种小文本列最多可以容纳 255 个字节,因此它最多可以容纳 85 个 3 字节或 63 个 4 字节字符。假设你有一个小文本使用的列utf8mb3但必须能够包含超过 63 个字符。您无法将其转换为utf8mb4除非您还将数据类型更改为更长的类型,例如文本.

    同样,一个很长的VARCHAR列可能需要更改为较长的列之一文本类型,如果你想从utf8mb3utf8mb4.

  • InnoDB对于使用的表,最大索引长度为 767 字节[紧凑](glossary.html#glos_compact_row_format)要么[冗余](glossary.html#glos_redundant_row_format)行格式,所以对于utf8mb3要么utf8mb4列,您最多可以分别索引 255 或 191 个字符。如果您目前有utf8mb3索引长度超过 191 个字符的列,您必须索引较少数量的字符。

    在一个InnoDB使用的表[紧凑](glossary.html#glos_compact_row_format)要么[冗余](glossary.html#glos_redundant_row_format)行格式,这些列和索引定义是合法的:

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

    使用utf8mb4相反,索引必须更小:

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

    笔记

    为了InnoDB使用的表[压缩](glossary.html#glos_compressed_row_format)要么[动态](glossary.html#glos_dynamic_row_format)行格式,索引键前缀允许超过 767 个字节(最多 3072 个字节)。使用这些行格式创建的表允许您为最多 1024 或 768 个字符编制索引utf8mb3要么utf8mb4列,分别。有关相关信息,请参阅第 15.22 节,“InnoDB 限制”, 和动态行格式.

    只有当您有很长的列或索引时,才最可能需要上述类型的更改。否则,您应该能够将您的表格从utf8mb3utf8mb4没有问题,使用更改表如前所述。

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

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

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

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

    如果您已转换为utf8mb4,utf16,utf16le, 要么utf32,然后决定转换回utf8mb3要么ucs2(例如,要降级到旧版本的 MySQL),这些注意事项适用:

  • utf8mb3ucs2数据应该没有问题。

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

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