Unicode 标准包括来自基本多语言平面 (BMP) 的字符和位于 BMP 之外的补充字符。
概要
BMP 字符的特征
- 它们的代码点值在0到65535之间 (或 U+0000 到 U+FFFF)
- 它们可以使用8位,16位或24位 (1到3个字节) 以可变长度编码进行编码
- 可以使用16位 (2个字节) 以固定长度对其进行编码
- 它们足以应付主要语言中的几乎所有字符
BMP 之外的补充字符
- 它们的代码点值在 U+10000 和 U+10FFFF 之间
- Unicode 对补充字符的支持要求字符集的范围超出 BMP 字符,因此比 BMP 字符占用更多的空间 (每个字符最多4个字节)
UTF-8
- 根据 RFC 3629 实现了用于对 Unicode 数据进行编码的 UTF-8 (具有8位单位的 Unicode 转换格式) 方法,该方法描述了从 1-4 个字节的编码序列。
- UTF-8 的思想是使用不同长度的字节序列对各种 Unicode 字符进行编码
- 基本的拉丁字母,数字和标点符号使用1个字节
- 大多数欧洲和中东的脚本字母均以2个字节的顺序排列
- 韩文,中文和日文使用3字节或4字节序列。
支持的 Unicode 字符集
常用字符集
- utf8mb4 (4字节 UTF-8 Unicode 编码)
- utf8mb4 是 utf8mb3 的超集
- 特点
- 支持 BMP 和补充字符
- 每个多字节字符使用 1-4 个字节,最多需要4个字节
- utf8mb3 (3字节 UTF-8 Unicode 编码)
已弃用,计划删除。
- 特点
- 仅支持 BMP 字符 (不支持补充字符)
- 每个多字节字符使用1-3个字节,最多需要3个字节
- utf8 是 utf8mb3 的别名;字符限制是隐式的,而不是名称中的显式
-
MySQL 立即将语句中的 utf8mb3 实例转换为 utf8,所以用户使用以下语句查看时看到的是 utf8
SHOW CREATE TABLE SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS
- 除去 CHARACTER SET 子句,其他地方也可以用 utf8mb3
mysqld --character-set-server=utf8mb3 SET NAMES 'utf8mb3'; /* and other SET statements that have similar effect */ SELECT _utf8mb3 'a';
- 特点
- utf8 (utf8mb3 的别名)
其他字符集
-
ucs2 (UCS-2 Unicode 编码)
- 特点
- 仅支持 BMP 字符 (不支持补充字符)
- 使用固定长度的16位编码,每个字符需要2个字节
- 特点
- utf16 (UTF-16 Unicode 编码)
- utf16 字符集是 ucs2 字符集加扩展名,可以对补充字符进行编码
-
每个字符使用2或4个字节
-
特点
- 对于 BMP 字符,utf16 和 ucs2 具有相同的存储特征:相同的代码值,相同的编码,相同的长度。
-
对于补充字符,utf16 具有一个特殊的序列,用于使用32位表示该字符。 这称为“代理”机制
- 由于 utf16 支持代理,而 ucs2 不支持,因此存在仅在 utf16 中适用的有效性检查:您不能在没有底部代理的情况下插入顶部代理
-
对于技术上有效但不是真正 Unicode 的字符 (即,Unicode 认为是“未分配的代码点”或“专用”字符,甚至是“非法”字符,如 0xffff ),没有有效性检查。
-
因为 MySQL 必须允许最坏的情况 (一个字符需要四个字节) ,所以 utf16 列或索引的最大长度仅为 ucs2 列或索引的最大长度的一半
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);
- utf16le (UTF16-LE 编码)
- 像 utf16一样,但是 little-endian 而不是 big-endian
- 每个字符使用2或4个字节
- utf32 (UTF-32 Unicode 编码)
- utf32 占用的空间是 ucs2 的两倍,也比 utf16 占用更多空间,但是 utf32 与 ucs2 一样具有可预测的存储优势:utf32 所需的字节数等于字符数乘以4。而且,与 utf16 不同, utf32 中没有编码技巧,因此存储的值等于代码值
- 每个字符使用4个字节
在3字节和4字节 Unicode 字符集之间转换
从 utf8mb3 转换为 utf8mb4 的一个优点是,应用程序可以使用补充字符。
utf8mb4 和 utf8mb3 区别
- utf8mb3 仅支持 BMP。utf8mb4 在 BMP 基础上,还支持补充字符
- utf8mb3 每个字符最多使用3个字节,utf8mb4 每个字符最多使用4个字节
就表内容而言,转换没有问题
- 对于 BMP 字符,utf8mb4 和 utf8mb3 具有相同的存储特征:相同的代码值,编码,长度
- 对于补充字符,utf8mb4 需要4个字节来存储它,而 utf8mb3 根本不能存储该字符。
- 将 utf8mb3 列转换为 utf8mb4 时,不必担心转换辅助字符,因为没有辅助字符
就表结构而言,存在某些不兼容性
- 对于可变长度字符数据类型 (VARCHAR 和 TEXT 类型),utf8mb4 列的字符允许的最大长度小于 utf8mb3 列的字符的最大允许长度
-
对于所有字符数据类型 (CHAR,VARCHAR 和 TEXT 类型),utf8mb4 列可索引的最大字符数少于 utf8mb3 列
-
因此,要将表从 utf8mb3 转换为 utf8mb4 ,可能需要更改某些列或索引定义
- 转换前
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;
- 转换
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 占3个字节,utf8mb4 占4个字节。对于 CHAR,VARCHAR 和 TEXT 数据类型需要注意
- 检查 utf8mb3 列的所有定义,并确保它们不超过存储引擎的最大长度
-
检查 utf8mb3 列上的所有索引,并确保它们不超过存储引擎的最大长度。有时,由于存储引擎的增强,最大值可能会更改
- TINYTEXT 列最多可容纳255个字节,因此最多可容纳85个3字节或63个4字节字符。VARCHAR 是类似的
-
对于使用 COMPACT 或 REDUNDANT 行格式的表,InnoDB 的最大索引长度为767字节,因此对于 utf8mb3 或 utf8mb4 列,您最多可以分别索引255个或191个字符
col1 VARCHAR(500) CHARACTER SET utf8, INDEX (col1(255)) col1 VARCHAR(500) CHARACTER SET utf8mb4, INDEX (col1(191))
回退需要考虑的因素
- utf8mb3 和 ucs2 数据应该没有问题
- 服务器必须具有足够的最新性,以识别引用所要转换的字符集的定义
- 对于引用 utf8mb4 字符集的对象定义,可以在降级之前使用 mysqldump 转储它们,编辑转储文件以将 utf8mb4 的实例更改为 utf8,然后在较旧的服务器中重新加载该文件,只要不使用4字节字符