• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 在3字节和4字节Unicode字符集之间转换

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

    注意

    该讨论主要集中在utf8mb3和之间的转换utf8mb4,但是类似的原理适用于ucs2字符集和字符集(例如utf16或)之间的转换utf32

    utf8mb3utf8mb4字符集的区别如下:

    • utf8mb3仅支持基本多语言平面(BMP)中的字符。utf8mb4另外还支持BMP之外的补充字符。
    • utf8mb3每个字符最多使用三个字节。utf8mb4每个字符最多使用四个字节。
    注意

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

    从转换的一个优点utf8mb3utf8mb4是,这使应用程序能够使用增补字符。一种折衷是这可能会增加数据存储空间需求。

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

    • 对于BMP字符,utf8mb4utf8mb3具有相同的存储特性:相同的代码值,相同的编码,相同的长度。
    • 对于补充字符,utf8mb4需要四个字节来存储它,而utf8mb3根本不能存储该字符。将utf8mb3列转换为时utf8mb4,您不必担心转换辅助字符,因为将没有补充字符。

    就表结构而言,这些是潜在的主要不兼容性:

    • 对于可变长度的字符数据类型(VARCHARTEXT类型),最大允许以字符长度不为utf8mb4比列utf8mb3的列。
    • 对于所有字符数据类型(CHARVARCHARTEXT类型),utf8mb4列的可索引最大字符数少于utf8mb3列。

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

    表可以从被转换utf8mb3utf8mb4通过使用ALTER TABLE。假设一个表具有以下定义:

    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为use 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是,列或索引键的最大长度(以字节单位)不变。因此,它在字符方面较小,因为字符的最大长度是四个字节而不是三个字节。对于CHARVARCHARTEXT数据类型,将你的MySQL表时观看了这些问题:

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

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

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

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

      同样,一个很长的VARCHAR列可能需要改变,以较长的一个TEXT类型,如果你想从转换utf8mb3utf8mb4

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

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

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

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

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

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

    仅当列或索引很长时,才有可能需要进行上述更改。否则,您应该可以使用前述方法将表从转换为utf8mb3utf8mb4而不会出现问题ALTER TABLE

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

    • SET NAMES 'utf8mb4'导致将4字节字符集用于连接字符集。只要服务器没有发送4字节字符,就不会有问题。否则,期望每个字符最多接收三个字节的应用程序可能会出现问题。相反,希望发送4字节字符的应用程序必须确保服务器能够理解它们。
    • 对于复制,如果要在主服务器上使用支持补充字符的字符集,则所有从服务器也必须理解它们。

      另外,请记住以下一般原则:如果表在主服务器和从服务器上具有不同的定义,则可能导致意外的结果。例如,最大索引键长度的差异使得utf8mb3在主机和utf8mb4从机上使用存在风险。

    如果你已经转换为utf8mb4utf16utf16le,或utf32,然后再决定转换回utf8mb3ucs2(例如,降级到旧版本的MySQL),这些事项:

    • utf8mb3并且ucs2数据应该没有问题。
    • 服务器必须具有足够的最新性,以识别引用所要转换的字符集的定义。
    • 对于引用utf8mb4字符集的对象定义,您可以在降级之前使用mysqldump将其转储,编辑转储文件以将的实例更改utf8mb4utf8,然后在较旧的服务器中重新加载该文件,只要其中不包含4字节字符即可。数据。较旧的服务器将utf8在转储文件中看到对象定义,并创建使用(3字节)utf8字符集的新对象。