Skip to content

Commit

Permalink
Merge branch 'docs-special-week' into refactor_privilege
Browse files Browse the repository at this point in the history
  • Loading branch information
lilin90 authored May 22, 2020
2 parents cf87ca2 + 832cc1f commit 4801b63
Show file tree
Hide file tree
Showing 14 changed files with 523 additions and 164 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/assign-to-project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Assign to Project

on:
issues:
types: [opened, labeled]
pull_request:
types: [opened, labeled]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
assign_one_project:
runs-on: ubuntu-latest
name: Assign to Project
steps:
- name: Assign NEW issues to Docs SIG project
uses: srggrs/assign-one-project-github-action@1.2.0
if: |
github.event_name == 'issues' &&
github.event.action == 'opened'
with:
project: 'https://github.com/pingcap/docs-cn/projects/1'
column_name: 'Issue: Backlog'
- name: Assign NEW pull requests to Docs SIG project
uses: srggrs/assign-one-project-github-action@1.2.0
if: |
github.event_name == 'pull_request' &&
github.event.action == 'opened'
with:
project: 'https://github.com/pingcap/docs-cn/projects/1'
column_name: 'PR: In Progress'
- name: Assign issues or PRs with translation-welcome label
uses: srggrs/assign-one-project-github-action@1.2.0
if: |
contains(github.event.issue.labels.*.name, 'translation/welcome') ||
contains(github.event.pull_request.labels.*.name, 'translation/welcome')
with:
project: 'https://github.com/pingcap/docs-cn/projects/2'
column_name: 'To do'
5 changes: 2 additions & 3 deletions TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,10 @@
+ [线上负载与 ADD INDEX 相互影响测试](/benchmark/online-workloads-and-add-index-operations.md)
+ 数据迁移
+ [支持的迁移路径](/ecosystem-tool-user-guide.md) @王相
+ [从 Oracle 迁移至 TiDB](/migrate-from-oracle-to-tidb.md) @王相
+ 从 MySQL 迁移至 TiDB
+ [从 CSV 文件迁移](/migrate-from-mysql-csv-files.md) @栾成
+ [从 Mydumper 文件迁移](/migrate-from-mysql-mydumper-files.md) @栾成
+ [使用 DM 工具从 Amazon Aurora MySQL 迁移](/migrate-from-aurora-mysql-database.md) @张学成,王相
+ [从 PostgreSQL 迁移至 TiDB](/migrate-from-postgresql-to-tidb.md) @王相
+ [从 CSV 文件迁移至 TiDB](/tidb-lightning/migrate-from-csv-using-tidb-lightning.md) @王相
+ 运维操作
+ 升级 TiDB 版本
Expand Down Expand Up @@ -109,11 +107,12 @@
+ 性能调优
+ 系统调优
+ [硬件](/tune-hardware-performance.md) @张文博
+ [操作系统](/tune-operating-system.md) @张文博
+ [操作系统性能参数调优](/tune-operating-system.md) @张文博
+ 软件调优
+ [软件版本](/tune-software-version.md) @张文博
+ 配置
+ [TiKV 调优](/tune-tikv-performance.md) @刘玮
+ [TiFlash 调优](/tiflash/tune-tiflash-performance.md)
+ SQL 性能调优 @崔一丁
+ [SQL 性能调优概览](/sql-tuning-overview.md)
+ [理解 TiDB 执行计划](/query-execution-plan.md)
Expand Down
202 changes: 202 additions & 0 deletions auto-increment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
title: AUTO_INCREMENT
category: reference
summary: 介绍 TiDB 的 `AUTO_INCREMENT` 列属性。
---

# AUTO_INCREMENT

本文介绍列属性 `AUTO_INCREMENT` 的基本概念、实现原理、自增相关的特性,以及使用限制。

## 基本概念

`AUTO_INCREMENT` 是用于自动填充缺省列值的列属性。当 `INSERT` 语句没有指定 `AUTO_INCREMENT` 列的具体值时,系统会自动地为该列分配一个值。该值满足唯一性,以及**特殊情况下**的递增性和连续性。使用示例如下:

{{< copyable "sql" >}}

```sql
create table t(id int primary key AUTO_INCREMENT, c int);
```

{{< copyable "sql" >}}

```sql
insert into t(c) values (1);
insert into t(c) values (2);
insert into t(c) values (3), (4), (5);
```

```sql
mysql> select * from t;
+----+---+
| id | c |
+----+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+----+---+
5 rows in set (0.01 sec)
```

此外,`AUTO_INCREMENT` 还支持显式指定列值的插入语句,此时 TiDB 会保存显式指定的值:

{{< copyable "sql" >}}

```sql
insert into t(id, c) values (6, 6);
```

```sql
mysql> select * from t;
+----+---+
| id | c |
+----+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
+----+---+
6 rows in set (0.01 sec)
```

以上用法和 MySQL 的 `AUTO_INCREMENT` 用法一致。但在隐式分配的具体值方面,TiDB 和 MySQL 之间具有较为显著的差异。

## 实现原理

TiDB 实现 `AUTO_INCREMENT` 隐式分配的原理是,对于每一个自增列,都使用一个全局可见的键值对用于记录当前已分配的最大 ID。由于分布式环境下的节点通信存在一定开销,为了避免写请求放大的问题,每个 TiDB 节点在分配 ID 时,都申请一段 ID 作为缓存,用完之后再去取下一段,而不是每次分配都向存储节点申请。例如,对于以下新建的表:

```sql
create table t(id int unique key AUTO_INCREMENT, c int);
```

假设集群中有两个 TiDB 实例 A 和 B,如果向 A 和 B 分别对 `t` 执行一条插入语句:

```sql
insert into t (c) values (1)
```

实例 A 可能会缓存 `[1,30000]` 的自增 ID,而实例 B 则可能缓存 `[30001,60000]` 的自增 ID。各自实例缓存的 ID 将随着执行将来的插入语句被作为缺省值,顺序地填充到 `AUTO_INCREMENT` 列中。

## 基本特性

### 唯一性保证

> **警告:**
>
> 在集群中有多个 TiDB 实例时,如果表结构中有自增 ID,建议不要混用显式插入和隐式分配(即自增列的缺省值和自定义值),否则可能会破坏隐式分配值的唯一性。
例如在上述示例中,依次执行如下操作:

1. 客户端向实例 B 插入一条将 `id` 设置为 `2` 的语句 `insert into t values (2, 1)`,并执行成功。
2. 客户端向实例 A 发送 `Insert` 语句 `insert into t (c) (1)`,这条语句中没有指定 `id` 的值,所以会由 A 分配。当前 A 缓存了 `[1, 30000]` 这段 ID,可能会分配 `2` 为自增 ID 的值,并把本地计数器加 `1`。而此时数据库中已经存在 `id``2` 的数据,最终返回 `Duplicated Error` 错误。

### 递增性保证

`AUTO_INCREMENT` 列隐式分配值的递增性只能在含有单个 TiDB 实例的集群中得到保证:即对于同一个自增列,先分配的值小于后分配的值;而在含有多个 TiDB 实例的集群中,无法保证自增列的递增性。

例如,对于上述例子,如果先向实例 B 执行一条插入语句,再向实例 A 执行一条插入语句。根据缓存自增 ID 的性质,自增列隐式分配的值可能分别是 `30002``2`。因此从时间上看,不满足递增性。

### 连续性保证

在含有多个 TiDB 实例的集群中,`AUTO_INCREMENT` 分配值的连续性**只能**在 batch insert 语句中得到保证。

例如,对以下表执行以下语句:

```sql
create table t (a int primary key AUTO_INCREMENT)
```

```sql
insert into t values (), (), (), ()
```

即使存在正在执行并发写入的其他 TiDB 实例,或者当前实例剩余的缓存 ID 数量不够,都不会影响分配值的连续性。

### `_tidb_rowid` 的关联性

> **注意:**
>
> 在没有指定整数类型主键的情况下 TiDB 会使用 `_tidb_rowid` 来标识行,该数值的分配会和自增列(如果存在的话)共用一个分配器,其中缓存的大小可能会被自增列和 `_tidb_rowid` 共同消耗。因此会有以下的示例情况:
```sql
mysql> create table t(id int unique key AUTO_INCREMENT);
Query OK, 0 rows affected (0.05 sec)

mysql> insert into t values (),(),();
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

mysql> select _tidb_rowid, id from t;
+-------------+------+
| _tidb_rowid | id |
+-------------+------+
| 4 | 1 |
| 5 | 2 |
| 6 | 3 |
+-------------+------+
3 rows in set (0.01 sec)
```

### 缓存大小控制

TiDB 自增 ID 的缓存大小在早期版本中是对用户透明的。从 v3.1.2、v3.0.14 和 v4.0.rc-2 版本开始,TiDB 引入了 `AUTO_ID_CACHE` 表选项来允许用户自主设置自增 ID 分配缓存的大小。例如:

```sql
mysql> create table t(a int auto_increment key) AUTO_ID_CACHE 100;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t values();
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> select * from t;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.01 sec)
```

此时如果将该列的自增缓存无效化,重新进行隐式分配:

```sql
mysql> delete from t;
Query OK, 1 row affected (0.01 sec)

mysql> rename table t to t1;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values()
Query OK, 1 row affected (0.00 sec)

mysql> select * from t;
+-----+
| a |
+-----+
| 101 |
+-----+
1 row in set (0.00 sec)
```

可以看到再一次分配的值为 `101`,说明该表的自增 ID 分配缓存的大小为 `100`

此外如果在批量插入的 `INSERT` 语句中所需连续 ID 长度超过 `AUTO_ID_CACHE` 的长度时,TiDB 会适当调大缓存以便能够保证该语句的正常插入。

### 自增步长和偏移量设置

从 v3.0.9 和 v4.0.rc-1 开始,和 MySQL 的行为类似,自增列隐式分配的值遵循 session 变量 `@@auto_increment_increment``@@auto_increment_offset` 的控制,其中自增列隐式分配的值 (ID) 将满足式子 `(ID - auto_increment_offset) % auto_increment_increment == 0`

## 使用限制

目前在 TiDB 中使用 `AUTO_INCREMENT` 有以下限制:

- 必须定义在主键或者唯一索引的列上。
- 只能定义在类型为整数、`FLOAT``DOUBLE` 的列上。
- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。
- 不支持使用 `ALTER TABLE` 来添加 `AUTO_INCREMENT` 属性。
- 支持使用 `ALTER TABLE` 来移除 `AUTO_INCREMENT` 属性。但从 TiDB 2.1.18 和 3.0.4 版本开始,TiDB 通过 session 变量 `@@tidb_allow_remove_auto_inc` 控制是否允许通过 `ALTER TABLE MODIFY``ALTER TABLE CHANGE` 来移除列的 `AUTO_INCREMENT` 属性,默认是不允许移除。
1 change: 1 addition & 0 deletions auto-random.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: AUTO_RANDOM
category: reference
summary: 本文介绍了 TiDB 的 `AUTO_RANDOM` 列属性。
aliases: ['/docs-cn/dev/reference/sql/attributes/auto-random/']
---

Expand Down
Loading

0 comments on commit 4801b63

Please sign in to comment.