Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql-statements: update ddl assertions behavior (#4680) #5272

Merged
merged 1 commit into from
Jan 6, 2021
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
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