Skip to content

Commit

Permalink
cherry pick #4680 to release-5.0 (#5272)
Browse files Browse the repository at this point in the history
Signed-off-by: ti-srebot <[email protected]>

Co-authored-by: TomShawn <[email protected]>
  • Loading branch information
ti-srebot and TomShawn authored Jan 6, 2021
1 parent ed4c8c2 commit f0faf75
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 31 deletions.
7 changes: 3 additions & 4 deletions mysql-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,16 @@ TiDB 主要使用 Prometheus 和 Grafana 来存储及查询相关的性能监控

### DDL 的限制

TiDB 中,所有支持的 DDL 变更操作都是在线执行的。可能与 MySQL 不同的是,在 TiDB 中,`ALGORITHM=INSTANT``ALGORITHM=INPLACE` 这两种 MySQL DDL 算法可用于指定使用哪种算法来修改表。

与 MySQL 相比,TiDB 中的 DDL 存在以下限制:
TiDB 中,所有支持的 DDL 变更操作都是在线执行的。与 MySQL 相比,TiDB 中的 DDL 存在以下限制:

* 不能在单条 `ALTER TABLE` 语句中完成多个操作。例如,不能在单个语句中添加多个列或索引,否则,可能会输出 `Unsupported multi schema change` 的错误。
* 不支持不同类型的索引 (`HASH|BTREE|RTREE|FULLTEXT`)。若指定了不同类型的索引,TiDB 会解析并忽略这些索引。
* 不支持添加/删除主键,除非开启了 [`alter-primary-key`](/tidb-configuration-file.md#alter-primary-key) 配置项。
* 不支持将字段类型修改为其超集,例如不支持从 `INTEGER` 修改为 `VARCHAR`,或者从 `TIMESTAMP` 修改为 `DATETIME`,否则可能输出的错误信息 `Unsupported modify column: type %d not match origin %d`
* 更改/修改数据类型时,尚未支持“有损更改”,例如不支持从 BIGINT 更改为 INT。
* 更改/修改十进制列时,不支持更改预置
* 更改/修改 DECIMAL 类型时,不支持更改精度
* 更改/修改整数列时,不允许更改 `UNSIGNED` 属性。
* TiDB 中,`ALGORITHM={INSTANT,INPLACE,COPY}` 语法只作为一种指定,并不更改 `ALTER` 算法,详情参阅 [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md)
* 分区表支持 Hash、Range 和 `Add`/`Drop`/`Truncate`/`Coalesce`。其他分区操作将被忽略,可能会报 `Warning: Unsupported partition type, treat as normal table` 错误。不支持以下分区表语法:
+ `PARTITION BY LIST`
+ `PARTITION BY KEY`
Expand Down
14 changes: 8 additions & 6 deletions sql-statements/sql-statement-alter-database.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@ summary: TiDB 数据库中 ALTER DATABASE 的使用概况。

## 示例

修改数据库 `test` 的字符集为 `utf8mb4`

{{< copyable "sql" >}}

```sql
ALTER {DATABASE | SCHEMA} [db_name]
alter_specification ...
alter_specification:
[DEFAULT] CHARACTER SET [=] charset_name
| [DEFAULT] COLLATE [=] collation_name
ALTER DATABASE test DEFAULT CHARACTER SET = utf8mb4;
```

```sql
Query OK, 0 rows affected (0.00 sec)
```

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

## MySQL 兼容性

Expand Down
82 changes: 61 additions & 21 deletions sql-statements/sql-statement-alter-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,30 @@ summary: TiDB 数据库中 ALTER TABLE 的使用概况。

## 示例

{{< copyable "sql" >}}

```sql
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL);
```

```
Query OK, 0 rows affected (0.11 sec)
```
创建一张表,并插入初始数据:

{{< copyable "sql" >}}

```sql
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL);
INSERT INTO t1 (c1) VALUES (1),(2),(3),(4),(5);
```

```
```sql
Query OK, 0 rows affected (0.11 sec)
Query OK, 5 rows affected (0.03 sec)
Records: 5 Duplicates: 0 Warnings: 0
```

执行以下查询需要扫描全表,因为 `c1` 列未被索引:

{{< copyable "sql" >}}

```sql
EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
```

```
```sql
+-------------------------+----------+-----------+---------------+--------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------+----------+-----------+---------------+--------------------------------+
Expand All @@ -64,38 +60,82 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
3 rows in set (0.00 sec)
```

你可以使用 [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-add-index.md) 语句在 `t1` 表上添加索引。添加后,`EXPLAIN` 的分析结果显示 `SELECT * FROM t1 WHERE c1 = 3;` 查询已使用效率更高的索引范围扫描:

{{< copyable "sql" >}}

```sql
ALTER TABLE t1 ADD INDEX (c1);
EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
```

```
```sql
Query OK, 0 rows affected (0.30 sec)
+------------------------+---------+-----------+------------------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
| IndexReader_6 | 10.00 | root | | index:IndexRangeScan_5 |
| └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:t1, index:c1(c1) | range:[3,3], keep order:false, stats:pseudo |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
2 rows in set (0.00 sec)
```

TiDB 允许用户为 DDL 操作指定使用某一种 `ALTER` 算法。这仅为一种指定,并不改变实际的用于更改表的算法。如果你只想在群集的高峰时段允许即时 DDL 更改,则 `ALTER` 算法会很有用。示例如下:

{{< copyable "sql" >}}

```sql
ALTER TABLE t1 DROP INDEX c1, ALGORITHM=INSTANT;
```

```sql
Query OK, 0 rows affected (0.24 sec)
```

如果某一 DDL 操作要求使用 `INPLACE` 算法,而用户指定 `ALGORITHM=INSTANT`,会导致报错:

{{< copyable "sql" >}}

```sql
EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
ALTER TABLE t1 ADD INDEX (c1), ALGORITHM=INSTANT;
```

```sql
ERROR 1846 (0A000): ALGORITHM=INSTANT is not supported. Reason: Cannot alter table by INSTANT. Try ALGORITHM=INPLACE.
```
+------------------------+---------+-----------+------------------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
| IndexReader_6 | 10.00 | root | | index:IndexRangeScan_5 |
| └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:t1, index:c1(c1) | range:[3,3], keep order:false, stats:pseudo |
+------------------------+---------+-----------+------------------------+---------------------------------------------+
2 rows in set (0.00 sec)

但如果为 `INPLACE` 操作指定 `ALGORITHM=COPY`,会产生警告而非错误,这是因为 TiDB 将该指定解读为*该算法或更好的算法*。由于 TiDB 使用的算法可能不同于 MySQL,所以这一行为可用于 MySQL 兼容性。

{{< copyable "sql" >}}

```sql
ALTER TABLE t1 ADD INDEX (c1), ALGORITHM=COPY;
SHOW WARNINGS;
```

```sql
Query OK, 0 rows affected, 1 warning (0.25 sec)
+-------+------+---------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+---------------------------------------------------------------------------------------------+
| Error | 1846 | ALGORITHM=COPY is not supported. Reason: Cannot alter table by COPY. Try ALGORITHM=INPLACE. |
+-------+------+---------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

## MySQL 兼容性

* 支持除空间类型外的所有数据类型。其它不支持的情况可参考:[DDL 语句与 MySQL 的兼容性情况](/mysql-compatibility.md#ddl-的限制)
TiDB 中的 `ALTER TABLE` 语法主要存在以下限制:

* 单条 `ALTER TABLE` 语句不能完成多项操作。
* 当前不支持有损更改,例如从 `BIGINT` 类型更改为 `INT` 类型。
* 不支持空间数据类型。

其它限制可参考:[TiDB 中 DDL 语句与 MySQL 的兼容性情况](/mysql-compatibility.md#ddl-的限制)

## 另请参阅

* [与 MySQL 兼容性对比](/mysql-compatibility.md#ddl-的限制)
* [ADD COLUMN](/sql-statements/sql-statement-add-column.md)
* [DROP COLUMN](/sql-statements/sql-statement-drop-column.md)
* [ADD INDEX](/sql-statements/sql-statement-add-index.md)
Expand Down

0 comments on commit f0faf75

Please sign in to comment.