Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@
- [约束](/reference/sql/constraints.md)
- [生成列](/reference/sql/generated-columns.md)
- [分区表](/reference/sql/partitioning.md)
- [字符集](/reference/sql/character-set.md)
- [字符集](/reference/sql/characterset-and-collation.md)
- [SQL 模式](/reference/sql/sql-mode.md)
- [SQL 诊断](/reference/system-databases/sql-diagnosis.md)
- [视图](/reference/sql/view.md)
Expand Down
6 changes: 6 additions & 0 deletions reference/configuration/tidb-server/configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ TiDB 配置文件比命令行参数支持更多的选项。你可以在 [config/
+ 默认值:[]
+ 默认情况下,该 list 名单为空,表示没有所需修复的坏表信息。

### `new_collations_enabled_on_first_bootstrap`

+ 用于开启新的 collation 支持
+ 默认值:false
+ 注意:该配置项只有在初次初始化集群时生效,初始化集群后,无法通过更改该配置项打开或关闭新的 collation 框架;4.0 版本之前的 TiDB 集群升级到 4.0 时,由于集群已经初始化过,该参数无论如何配置,都作为 false 处理。

### `max-server-connections`

+ TiDB 中同时允许的最大客户端连接数,用于资源控制。
Expand Down
9 changes: 0 additions & 9 deletions reference/mysql-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ TiDB 支持 MySQL 传输协议及其绝大多数的语法。这意味着您现
* 外键约束
* 全文/空间函数与索引
* 非 `ascii`/`latin1`/`binary`/`utf8`/`utf8mb4` 的字符集
* `BINARY` 之外的排序规则
* SYS schema
* MySQL 追踪优化器
* XML 函数
Expand Down Expand Up @@ -118,8 +117,6 @@ TiDB 支持常用的 MySQL 内建函数,但是不是所有的函数都已经
- 不支持修改 `DECIMAL` 类型的精度
- 不支持更改 `UNSIGNED` 属性
- 只支持将 `CHARACTER SET` 属性从 `utf8` 更改为 `utf8mb4`
+ Alter Database
- 只支持将 `CHARACTER SET` 属性从 `utf8` 更改为 `utf8mb4`
+ `LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}`: TiDB 支持的语法,但是在 TiDB 中不会生效。所有支持的 DDL 变更都不会锁表。
+ `ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}`: TiDB 完全支持 `ALGORITHM=INSTANT` 和 `ALGORITHM=INPLACE` 语法,但运行过程与 MySQL 有所不同,因为 MySQL 中的一些 `INPLACE` 操作实际上是 TiDB 中的 `INSTANT` 操作。`ALGORITHM=COPY` 语法在 TiDB 中不会生效,会返回警告信息。
+ 单个 `ALTER TABLE` 语句中无法完成多个操作。例如,不能用一个语句来添加多个列或多个索引。
Expand Down Expand Up @@ -233,12 +230,6 @@ TiDB 不需要导入时区表数据也能使用所有时区名称,采用系统

与 MySQL 一样,TiDB 默认启用了 `NO_ZERO_DATE` 和 `NO_ZERO_IN_DATE` 模式,不建议将这两个模式设为禁用。尽管将这些模式设为禁用时 TiDB 仍可正常使用,但 TiKV coprocessor 会受到影响,具体表现为,执行特定类型的语句,将日期和时间处理函数下推到 TiKV 时可能会导致语句错误。

#### 字符串类型行末空格的处理

目前 TiDB 在进行数据插入时,对于 `VARCHAR` 类型会保留行末空格,对于 `CHAR` 类型会插入截断空格后的数据。在没有索引的情况下,TiDB 和 MySQL 行为保持一致。如果 `VARCHAR` 类型上有 `UNIQUE` 索引,MySQL 在判断是否重复的时候,和处理 `CHAR` 类型一样,先截断 `VARCHAR` 数据末行空格再作判断;TiDB 则是按照保留空格的情况处理。

在做比较时,MySQL 会先截去常量和 Column 的末尾空格再作比较,而 TiDB 则是保留常量和 Column 的末尾空格来做精确比较。

### 类型系统的区别

以下的列类型 MySQL 支持,但 TiDB 不支持:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
---
title: 字符集支持
title: 字符集和排序规则
category: reference
aliases: ['/docs-cn/v4.0/reference/sql/character-set/']
---

# 字符集支持

名词解释,下面的阐述中会交错使用中文或者英文,请互相对照:
下面的阐述中会交错使用中文或者英文,请互相对照:

* Character Set:字符集
* Collation:排序规则
Expand Down Expand Up @@ -33,71 +34,27 @@ SHOW CHARACTER SET;

> **注意:**
>
> - 在 `TiDB` 中 `utf8` 被当做成了 `utf8mb4` 来处理。
> - 每种字符集都对应一个默认的 Collation,当前有且仅有一个。
> - 每种字符集都对应一个默认的 Collation,并且仅有一个。

对于字符集来说,至少会有一个 Collation(排序规则)与之对应。而大部分字符集实际上会有多个 Collation。利用以下的语句可以查看
对于字符集来说,至少会有一个 Collation(排序规则)与之对应。利用以下的语句可以查看字符集对应的排序规则(以下是[新的 Collation 框架](#新框架下的-collation-支持))下的结果

{{< copyable "sql" >}}

```sql
SHOW COLLATION WHERE Charset = 'latin1';
SHOW COLLATION WHERE Charset = 'utf8mb4';
```

```
+-------------------|---------|------|---------|----------|---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------|---------|------|---------|----------|---------+
| latin1_german1_ci | latin1 | 5 | | Yes | 1 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |
| latin1_danish_ci | latin1 | 15 | | Yes | 1 |
| latin1_german2_ci | latin1 | 31 | | Yes | 1 |
| latin1_bin | latin1 | 47 | | Yes | 1 |
| latin1_general_ci | latin1 | 48 | | Yes | 1 |
| latin1_general_cs | latin1 | 49 | | Yes | 1 |
| latin1_spanish_ci | latin1 | 94 | | Yes | 1 |
+-------------------|---------|------|---------|----------|---------+
8 rows in set (0.00 sec)
+--------------------+---------+------+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+--------------------+---------+------+---------+----------+---------+
| utf8mb4_bin | utf8mb4 | 46 | Yes | Yes | 1 |
| utf8mb4_general_ci | utf8mb4 | 45 | | Yes | 1 |
+--------------------+---------+------+---------+----------+---------+
2 rows in set (0.00 sec)
```

`latin1` Collation(排序规则)分别有以下含义:

| Collation | 含义 |
|:------------------|:----------------------------------|
| latin1_bin | latin1 编码的二进制表示 |
| latin1_danish_ci | 丹麦语/挪威语,不区分大小写 |
| latin1_general_ci | 多种语言的 (西欧),不区分大小写 |
| latin1_general_cs | 多种语言的 (ISO 西欧),区分大小写 |
| latin1_german1_ci | 德国 DIN-1 (字典序),不区分大小写 |
| latin1_german2_ci | 德国 DIN-2,不区分大小写 |
| latin1_spanish_ci | 现代西班牙语,不区分大小写 |
| latin1_swedish_ci | 瑞典语/芬兰语,不区分大小写 |

每一个字符集,都有一个默认的 Collation,例如 `utf8` 的默认 Collation 就为 `utf8_bin`。

> **注意:**
>
> `TiDB` 目前的 Collation 只支持区分大小写的比较排序规则。

## Collation 命名规则

`TiDB` 的 Collation 遵循着如下的命名规则:

* Collation 的前缀是它相应的字符集,通常之后会跟着一个或者更多的后缀来表名其他的排序规则, 例如:utf8_general_ci 和 lation1_swedish_ci 是 utf8
和 latin1 字符集的 Collation。但是 binary 字符集只有一个 Collation,就是 binary。
* 一个语言对应的 Collation 会包含语言的名字,例如 utf8_turkish_ci 和 utf8_hungarian_ci 是依据 Turkish(土耳其语) 和 Hungarian(匈牙利语) 的排序规则来排序。
* Collation 的后缀表示了 Collation 是否区分大小写和是否区分口音。下面的表展示了这些特性:

| 后缀 | 含义 |
|:-----|:---------------------------------|
| \_ai | 口音不敏感(Accent insensitive) |
| \_as | 口音敏感 (Accent sensitive) |
| \_ci | 大小写不敏感 |
| \_cs | 大小写敏感 |

> **注意:**
>
> 目前为止 TiDB 只支持部分以上提到的 Collation。
每一个字符集,都有一个默认的 Collation,例如 `utf8mb4` 的默认 Collation 为 `utf8mb4_bin`。

## 集群 Character Set 和 Collation

Expand Down Expand Up @@ -126,7 +83,7 @@ ALTER DATABASE db_name
{{< copyable "sql" >}}

```sql
create schema test1 character set utf8 COLLATE uft8_general_ci;
create schema test1 character set utf8mb4 COLLATE uft8mb4_general_ci;
```

```
Expand All @@ -153,15 +110,15 @@ SELECT @@character_set_database, @@collation_database;
+--------------------------|----------------------+
| @@character_set_database | @@collation_database |
+--------------------------|----------------------+
| utf8 | uft8_general_ci |
| utf8mb4 | uft8mb4_general_ci |
+--------------------------|----------------------+
1 row in set (0.00 sec)
```

{{< copyable "sql" >}}

```sql
create schema test2 character set latin1 COLLATE latin1_general_ci;
create schema test2 character set latin1 COLLATE latin1_bin;
```

```
Expand All @@ -188,7 +145,7 @@ SELECT @@character_set_database, @@collation_database;
+--------------------------|----------------------+
| @@character_set_database | @@collation_database |
+--------------------------|----------------------+
| latin1 | latin1_general_ci |
| latin1 | latin1_bin |
+--------------------------|----------------------+
1 row in set (0.00 sec)
```
Expand Down Expand Up @@ -221,7 +178,7 @@ ALTER TABLE tbl_name
{{< copyable "sql" >}}

```sql
CREATE TABLE t1(a int) CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE t1(a int) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
```

```
Expand Down Expand Up @@ -260,8 +217,8 @@ col_name {ENUM | SET} (val_list)

```sql
SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;
SELECT _utf8mb4'string';
SELECT _utf8mb4'string' COLLATE utf8mb4_general_ci;
```

规则,如下:
Expand All @@ -283,7 +240,7 @@ SELECT _latin1'string' COLLATE latin1_danish_ci;

* `SET NAMES 'charset_name' [COLLATE 'collation_name']`

`SET NAMES` 用来设定客户端会在之后的请求中使用的字符集。`SET NAMES utf8` 表示客户端会在接下来的请求中,都使用 utf8 字符集。服务端也会在之后返回结果的时候使用 utf8 字符集。
`SET NAMES` 用来设定客户端会在之后的请求中使用的字符集。`SET NAMES utf8mb4` 表示客户端会在接下来的请求中,都使用 utf8mb4 字符集。服务端也会在之后返回结果的时候使用 utf8mb4 字符集。
`SET NAMES 'charset_name'` 语句其实等于下面语句的组合:

{{< copyable "sql" >}}
Expand All @@ -310,7 +267,7 @@ SET collation_connection = @@collation_database;

## 集群,服务器,数据库,表,列,字符串 Character Sets 和 Collation 优化级

字符串 => 列 => 表 => 数据库 => 服务器 => 集群
字符串 > 列 > 表 > 数据库 > 服务器 > 集群

## Character Sets 和 Collation 通用选择规则

Expand All @@ -324,4 +281,106 @@ SET collation_connection = @@collation_database;

如果不希望报错,可以通过 `set @@tidb_skip_utf8_check=1;` 跳过字符检查。

## 排序规则支持

Collation 的语法支持和语义支持受到配置项 [`new_collation_enable`](/reference/configuration/tidb-server/configuration-file.md#new_collations_enabled_on_first_bootstrap) 的影响。这里语法支持和语义支持有所区别。语法支持是指 TiDB 能够解析和设置 Collation;而语义支持是指 TiDB 能够在比较字符串时正确地使用 Collation。

在 4.0 版本之前,TiDB 只提供了旧的 Collation 框架,能够在语法上支持的绝大部分 MySQL Collation,但语义上所有的 Collation 都当成 binary Collation。

4.0 版本中,TiDB 增加了新的 Collation 框架用于在语义上支持不同的 Collation,保证字符串比较时严格遵循对应的 Collation,详情请见下文。

### 旧框架下的 Collation 支持

在 4.0 版本之前,TiDB 中可以指定大部分 MySQl 中的 Collation,并把这些 Collation 按照默认 Collation 处理,即以编码字节序为字符定序。和 MySQL 不同的是,TiDB 在比较字符前按照 Collation 的 `PADDING` 属性将字符补齐空格,因此会造成以下的行为区别:

{{< copyable "sql" >}}

```sql
create table t(a varchar(20) charset utf8mb4 collate utf8mb4_general_ci primary key);
Query OK, 0 rows affected
insert into t values ('A');
Query OK, 1 row affected
insert into t values ('a');
Query OK, 1 row affected # MySQL 中,由于 utf8mb4_general_ci 大小写不敏感,报错 Duplicate entry 'a'。
insert into t1 values ('a ');
Query OK, 1 row affected # MySQL 中,由于补齐空格比较,报错 Duplicate entry 'a '。
```

### 新框架下的 Collation 支持

TiDB 4.0 新增了完整的 Collation 支持框架,从语义上支持了 Collation,并新增了配置开关 `new_collation_enabled_on_first_boostrap`,在集群初次初始化时决定是否启用新 Collation 框架。在该配置开关打开之后初始化集群,可以通过 `mysql`.`tidb` 表中的 `new_collation_enabled` 变量确认新 Collation 是否启用:

{{< copyable "sql" >}}

```sql
select VARIABLE_VALUE from mysql.tidb where VARIABLE_NAME='new_collation_enabled';
```

```
+----------------+
| VARIABLE_VALUE |
+----------------+
| True |
+----------------+
1 row in set (0.00 sec)
```

在新的 Collation 框架下,TiDB 能够支持 `utf8_general_ci` 和 `utf8mb4_general_ci` 这两种 Collation, 其排序规则与 MySQL 兼容。

使用 `utf8_general_ci` 或者 `utf8mb4_general_ci` 时,字符串之间的比较是大小写不敏感 (case-insensitive) 和口音不敏感 (accent-insensitive) 的。同时,TiDB 还修正了 Collation 的 `PADDING` 行为:

{{< copyable "sql" >}}

```sql
create table t(a varchar(20) charset utf8mb4 collate utf8mb4_general_ci primary key);
Query OK, 0 rows affected (0.00 sec)
insert into t values ('A');
Query OK, 1 row affected (0.00 sec)
insert into t values ('a');
ERROR 1062 (23000): Duplicate entry 'a' for key 'PRIMARY'
insert into t values ('a ');
ERROR 1062 (23000): Duplicate entry 'a ' for key 'PRIMARY'
```

> **注意:**
>
> TiDB 中 padding 的实现方式与 MySQL 的不同。在 MySQL 中,padding 是通过补齐空格实现的。而在 TiDB 中 padding 是通过裁剪掉末尾的空格来实现的。两种做法在绝大多数情况下是一致的,唯一的例外是字符串尾部包含小于空格 (0x20) 的字符时,例如 `'a' < 'a\t'` 在 TiDB 中的结果为 `1`,而在 MySQL 中,其等价于 `'a ' < 'a\t'`,结果为 `0`。

## 表达式中 Collation 的 Coercibility 值

如果一个表达式涉及多个不同 Collation 的子表达式时,需要对计算时用的 Collation 进行推断,规则如下:

1. 显式 `COLLATE` 子句的 coercibility 值为 `0`。
2. 如果两个字符串的 Collation 不兼容,这两个字符串 `concat` 结果的 coercibility 值为 `1`。目前所实现的 Collation 都是互相兼容的。
3. 列的 Collation 的 coercibility 值为 `2`。
4. 系统常量(`USER()` 或者 `VERSION()` 返回的字符串)的 coercibility 值为 `3`。
5. 常量的 coercibility 值为 `4`。
6. 数字或者中间变量的 coercibility 值为 `5`。
7. `NULL` 或者由 `NULL` 派生出的表达式的 coercibility 值为 `6`。

在推断 Collation 时,TiDB 优先使用 coercibility 值较低的表达式的 Collation(与 MySQL 一致)。如果 coercibility 值相同,则按以下优先级确定 Collation:

binary > utf8mb4_bin > utf8mb4_general_ci > utf8_bin > utf8_general_ci > latin1_bin > ascii_bin

如果两个子表达式的 Collation 不相同,而且表达式的 coercibility 值都为 `0` 时,TiDB无法推断 Collation 并报错。

## `COLLATE` 子句

TiDB 支持使用 `COLLATE` 子句来指定一个表达式的 Collation,该表达式的 coercibility 值为 `0`,具有最高的优先级。示例如下:

{{< copyable "sql" >}}

```sql
select 'a' = 'A' collate utf8mb4_general_ci;
```

```
+--------------------------------------+
| 'a' = 'A' collate utf8mb4_general_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
1 row in set (0.00 sec)
```

更多细节,参考 [Connection Character Sets and Collations](https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html)。
2 changes: 1 addition & 1 deletion reference/sql/statements/alter-database.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ alter_specification:
| [DEFAULT] COLLATE [=] collation_name
```

`alter_specification` 选项用于指定数据库具体的 `CHARACTER SET` 和 `COLLATE`。目前 TiDB 只支持部分的字符集和排序规则,请参照[字符集支持](/reference/sql/character-set.md)。
`alter_specification` 选项用于指定数据库具体的 `CHARACTER SET` 和 `COLLATE`。目前 TiDB 只支持部分的字符集和排序规则,请参照[字符集支持](/reference/sql/characterset-and-collation.md)。

## 另请参阅

Expand Down
2 changes: 1 addition & 1 deletion reference/sql/statements/create-database.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ create_specification:

当创建已存在的数据库且不指定使用 `IF NOT EXISTS` 时会报错。

`create_specification` 选项用于指定数据库具体的 `CHARACTER SET` 和 `COLLATE`。目前 TiDB 只支持部分的字符集和排序规则,请参照[字符集支持](/reference/sql/character-set.md)。
`create_specification` 选项用于指定数据库具体的 `CHARACTER SET` 和 `COLLATE`。目前 TiDB 只支持部分的字符集和排序规则,请参照[字符集支持](/reference/sql/characterset-and-collation.md)。

## 示例

Expand Down
2 changes: 1 addition & 1 deletion reference/sql/statements/set-names.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ SHOW VARIABLES LIKE 'character_set%';

* [SHOW \[GLOBAL|SESSION\] VARIABLES](/reference/sql/statements/show-variables.md)
* [SET <variable>](/reference/sql/statements/set-variable.md)
* [Character Set Support](/reference/sql/character-set.md)
* [Character Set Support](/reference/sql/characterset-and-collation.md)
2 changes: 1 addition & 1 deletion reference/system-databases/information-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ select * from `ANALYZE_STATUS`;

## CHARACTER_SETS 表

`CHARACTER_SETS` 表提供[字符集](/reference/sql/character-set.md)相关的信息。TiDB 目前仅支持部分字符集。
`CHARACTER_SETS` 表提供[字符集](/reference/sql/characterset-and-collation.md)相关的信息。TiDB 目前仅支持部分字符集。

{{< copyable "sql" >}}

Expand Down
2 changes: 1 addition & 1 deletion reference/tools/syncer.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ target-table = "order_2017"

6. 检查字符集。

TiDB 和 MySQL 的字符集的兼容性不同,详见 [TiDB 支持的字符集](/reference/sql/character-set.md)。
TiDB 和 MySQL 的字符集的兼容性不同,详见 [TiDB 支持的字符集](/reference/sql/characterset-and-collation.md)。

7. 检查同步的表是否都有主键或者唯一索引。

Expand Down