MySQL 8.4 Release Notes
12.9.5 UTF-16 字符集(UTF-16 Unicode 编码)
utf16 字符集是 ucs2 字符集的扩展,支持补充字符编码:
-
对于 BMP 字符,
utf16和ucs2都有相同的存储特性:同样的代码值、同样的编码、同样的长度。 -
对于补充字符,
utf16使用 32 位特殊序列来表示该字符,这称为“代理”机制:对于大于0xffff的数字,取 10 位,添加到0xd800中,并将其放入第一个 16 位单元中,然后取 10 位,添加到0xdc00中,并将其放入下一个 16 位单元中。因此,所有补充字符都需要 32 位,其中前 16 位是介于0xd800和0xdbff之间的数字,而后 16 位是介于0xdc00和0xdfff之间的数字。示例在 Unicode 4.0 文件的第 15.5 代理区 部分中。
因为 utf16 支持代理,而 ucs2 不支持,所以只有在 utf16 中才会出现有效性检查:你不能插入顶级代理没有底级代理,或者反之。例如:
INSERT INTO t (ucs2_column) VALUES (0xd800); /* legal */
INSERT INTO t (utf16_column)VALUES (0xd800); /* illegal */
技术上来说,MySQL 对于所有有效的字符都没有验证,只有 Unicode 认为是未分配代码点、私用代码点或非法字符(如 0xffff)。例如,因为 U+F8FF 是苹果Logo,这是合法的:
INSERT INTO t (utf16_column)VALUES (0xf8ff); /* legal */
这些字符不能被期望对每个人都有相同的含义。
因为 MySQL 必须允许最坏的情况(一个字符需要四个字节),所以 utf16 列或索引的最大长度只是一半的 ucs2 列或索引的最大长度。例如,MEMORY 表索引键的最大长度是 3072 字节,所以这些语句创建了最长允许的索引对 ucs2 和 utf16 列:
CREATE TABLE tf (s1 VARCHAR(1536) CHARACTER SET ucs2) ENGINE=MEMORY;
CREATE INDEX i ON tf (s1);
CREATE TABLE tg (s1 VARCHAR(768) CHARACTER SET utf16) ENGINE=MEMORY;
CREATE INDEX i ON tg (s1);