MySQL 兼容性
TiDB 高度兼容 MySQL 协议,以及 MySQL 5.7 和 MySQL 8.0 的常用特性和语法。MySQL 的生态工具(PHPMyAdmin、Navicat、MySQL Workbench、DBeaver 以及 更多)和 MySQL 客户端均可用于 TiDB。
然而,TiDB 并不支持 MySQL 的部分特性。这可能是因为现在有更好的方式来解决相关问题(例如使用 JSON 替代 XML 函数),或者当前需求较少且实现成本较高(如存储过程和函数)。此外,某些特性在分布式系统中实现难度较大。
你可以在 TiDB Playground 上体验 TiDB 的相关特性。
不支持的特性
存储过程和函数
触发器
事件
用户自定义函数
FULLTEXT语法和索引 #1793SPATIAL(也称为GIS/GEOMETRY)函数、数据类型和索引 #6347除
ascii、latin1、binary、utf8、utf8mb4和gbk以外的字符集优化器追踪
XML 函数
X-Protocol #1109
列级权限 #9766
XA语法(TiDB 内部使用两阶段提交,但未通过 SQL 接口暴露)CREATE TABLE tblName AS SELECT stmt语法 #4754CHECK TABLE语法 #4673CHECKSUM TABLE语法 #1895REPAIR TABLE语法OPTIMIZE TABLE语法HANDLER语句CREATE TABLESPACE语句“Session Tracker: Add GTIDs context to the OK packet”
降序索引 #2519
SKIP LOCKED语法 #18207Lateral 派生表 #40328
JOIN ON 子查询 #11414
与 MySQL 的差异
自增 ID
在 TiDB 中,自增列的值(ID)在单个 TiDB 实例内是全局唯一且递增的。若需在多 TiDB 实例间保证递增,可以使用
AUTO_INCREMENTMySQL 兼容模式。但分配的 ID 不一定严格连续,因此建议避免混用默认值和自定义值,以防出现Duplicated Error错误。你可以通过
tidb_allow_remove_auto_inc系统变量来允许或禁止移除AUTO_INCREMENT列属性。移除列属性时,可使用ALTER TABLE MODIFY或ALTER TABLE CHANGE语法。TiDB 不支持新增
AUTO_INCREMENT列属性,且一旦移除后无法恢复。在 TiDB v6.6.0 及更早版本中,自增列行为与 MySQL InnoDB 一致,要求其为主键或索引前缀。从 v7.0.0 起,TiDB 移除了该限制,允许更灵活的表主键定义。#40580
更多细节参见 AUTO_INCREMENT。
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, 1 rows affected (0.00 sec)
mysql> INSERT INTO t VALUES();
Query OK, 1 rows affected (0.00 sec)
mysql> INSERT INTO t VALUES();
Query OK, 1 rows affected (0.00 sec)
mysql> SELECT _tidb_rowid, id FROM t;
+-------------+------+
| _tidb_rowid | id |
+-------------+------+
| 2 | 1 |
| 4 | 3 |
| 6 | 5 |
+-------------+------+
3 rows in set (0.01 sec)
如上所示,由于共用分配器,id 每次递增 2。该行为在 MySQL 兼容模式 下会发生变化,此时不再共用分配器,因此不会跳号。
性能模式(Performance schema)
在 TiDB Cloud 中,你可以在 TiDB Cloud 控制台的集群概览页面查看性能指标,或使用 第三方监控集成。在 TiDB 中,大多数 performance schema 表 返回空结果。
查询执行计划
TiDB 中查询执行计划(EXPLAIN/EXPLAIN FOR)的输出格式、内容和权限设置与 MySQL 有较大差异。
在 TiDB 中,MySQL 系统变量 optimizer_switch 为只读,对查询计划无影响。虽然优化器 Hint 语法与 MySQL 类似,但可用的 Hint 及其实现可能不同。
更多信息参见 理解查询执行计划。
内置函数
TiDB 支持大多数 MySQL 内置函数,但并非全部。你可以使用 SHOW BUILTINS 语句获取可用函数列表。
DDL 操作
在 TiDB 中,所有支持的 DDL 变更均可在线完成。但与 MySQL 相比,TiDB 在 DDL 操作上有以下主要限制:
使用单条
ALTER TABLE语句修改同一张表的多个 schema 对象(如列或索引)时,不支持对同一对象进行多次变更。例如,执行ALTER TABLE t1 MODIFY COLUMN c1 INT, DROP COLUMN c1会报Unsupported operate same column/index错误。不支持通过单条
ALTER TABLE语句同时修改多个 TiDB 特有的 schema 对象,如TIFLASH REPLICA、SHARD_ROW_ID_BITS和AUTO_ID_CACHE。TiDB 不支持通过
ALTER TABLE修改某些数据类型。例如,不支持将DECIMAL类型修改为DATE类型。若数据类型变更不被支持,TiDB 会报Unsupported modify column: type %d not match origin %d错误。详见ALTER TABLE。ALGORITHM={INSTANT,INPLACE,COPY}语法在 TiDB 中仅作为断言存在,不会改变ALTER算法。详见ALTER TABLE。不支持对
CLUSTERED类型的主键进行添加/删除。关于CLUSTERED类型主键的更多信息,参见 聚簇索引。不支持不同类型的索引(
HASH|BTREE|RTREE|FULLTEXT),指定时会被解析但忽略。TiDB 支持
HASH、RANGE、LIST和KEY分区类型。对于不支持的分区类型,TiDB 返回Warning: Unsupported partition type %s, treat as normal table,其中%s为具体不支持的分区类型。Range、Range COLUMNS、List 和 List COLUMNS 分区表支持
ADD、DROP、TRUNCATE和REORGANIZE操作。其他分区操作会被忽略。Hash 和 Key 分区表支持
ADD、COALESCE和TRUNCATE操作。其他分区操作会被忽略。分区表不支持以下语法:
SUBPARTITION{CHECK|OPTIMIZE|REPAIR|IMPORT|DISCARD|REBUILD} PARTITION更多分区相关内容,参见 分区表。
表分析
在 TiDB 中,统计信息收集 与 MySQL 不同,会完全重建表的统计信息,因此资源消耗更大,耗时更长。而 MySQL/InnoDB 执行的是相对轻量、耗时较短的操作。
更多信息参见 ANALYZE TABLE。
SELECT 语法限制
TiDB 不支持以下 SELECT 语法:
SELECT ... INTO @variableSELECT .. GROUP BY expr不像 MySQL 5.7 那样隐式等同于GROUP BY expr ORDER BY expr。
更多细节参见 SELECT 语句参考。
UPDATE 语句
参见 UPDATE 语句参考。
视图
TiDB 中的视图不可更新,不支持 UPDATE、INSERT、DELETE 等写操作。
临时表
更多信息参见 TiDB 本地临时表与 MySQL 临时表的兼容性。
字符集与排序规则
关于 TiDB 支持的字符集与排序规则,参见 字符集与排序规则概述。
关于 GBK 字符集的 MySQL 兼容性,参见 GBK 兼容性。
TiDB 继承表所用字符集作为国家字符集。
存储引擎
TiDB 允许使用其他存储引擎创建表。尽管如此,TiDB 描述的元数据仍为 InnoDB 存储引擎,以保证兼容性。
SQL 模式
TiDB 支持大多数 SQL 模式:
- 兼容性模式,如
Oracle和PostgreSQL,会被解析但被忽略。兼容性模式在 MySQL 5.7 中已废弃,在 MySQL 8.0 中已移除。 ONLY_FULL_GROUP_BY模式与 MySQL 5.7 存在 语义差异。- MySQL 的
NO_DIR_IN_CREATE和NO_ENGINE_SUBSTITUTIONSQL 模式为兼容性接受,但在 TiDB 中无实际意义。
默认差异
TiDB 与 MySQL 5.7 和 MySQL 8.0 的默认值存在如下差异:
- 默认字符集:
- TiDB 默认值为
utf8mb4。 - MySQL 5.7 默认值为
latin1。 - MySQL 8.0 默认值为
utf8mb4。
- TiDB 默认值为
- 默认排序规则:
- TiDB 默认排序规则为
utf8mb4_bin。 - MySQL 5.7 默认排序规则为
utf8mb4_general_ci。 - MySQL 8.0 默认排序规则为
utf8mb4_0900_ai_ci。
- TiDB 默认排序规则为
- 默认 SQL 模式:
- TiDB 默认 SQL 模式包含:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION。 - MySQL 默认 SQL 模式:
- MySQL 5.7 的默认 SQL 模式与 TiDB 相同。
- MySQL 8.0 的默认 SQL 模式包含:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION。
- TiDB 默认 SQL 模式包含:
lower_case_table_names的默认值:- TiDB 默认值为
2,且目前仅支持2。 - MySQL 默认值如下:
- Linux 上为
0,表示表名和数据库名在磁盘上按CREATE TABLE或CREATE DATABASE语句指定的大小写存储,名称比较区分大小写。 - Windows 上为
1,表示表名在磁盘上以小写存储,名称比较不区分大小写。MySQL 在存储和查找时会将所有表名转换为小写。该行为同样适用于数据库名和表别名。 - macOS 上为
2,表示表名和数据库名在磁盘上按CREATE TABLE或CREATE DATABASE语句指定的大小写存储,但 MySQL 在查找时会将其转换为小写,名称比较不区分大小写。
- Linux 上为
- TiDB 默认值为
explicit_defaults_for_timestamp的默认值:- TiDB 默认值为
ON,且目前仅支持ON。 - MySQL 默认值如下:
- MySQL 5.7:
OFF。 - MySQL 8.0:
ON。
- MySQL 5.7:
- TiDB 默认值为
日期与时间
TiDB 支持命名时区,具体说明如下:
- TiDB 使用系统当前安装的所有时区规则(通常为
tzdata包)进行计算,因此可以直接使用所有时区名称,无需导入时区表数据。导入时区表数据不会改变计算规则。 - 当前 MySQL 默认使用本地时区,然后依赖系统内置的当前时区规则(如夏令时切换)进行计算。若未导入时区表数据,MySQL 无法通过名称指定时区。
类型系统差异
以下列类型为 MySQL 支持但 TiDB 不支持:
SQL_TSI_*(包括 SQL_TSI_MONTH、SQL_TSI_WEEK、SQL_TSI_DAY、SQL_TSI_HOUR、SQL_TSI_MINUTE 和 SQL_TSI_SECOND,但不包括 SQL_TSI_YEAR)
正则表达式
关于 TiDB 正则表达式与 MySQL 的兼容性,包括 REGEXP_INSTR()、REGEXP_LIKE()、REGEXP_REPLACE() 和 REGEXP_SUBSTR(),参见 正则表达式与 MySQL 的兼容性。
由于废弃特性导致的不兼容
TiDB 未实现 MySQL 中已废弃的部分特性,包括:
CREATE RESOURCE GROUP、DROP RESOURCE GROUP 和 ALTER RESOURCE GROUP 语句
以下用于创建、修改和删除资源组的语句,其支持的参数与 MySQL 不同。详情参见以下文档:
TiDB 与 MySQL InnoDB 悲观事务(锁)的差异
关于 TiDB 与 MySQL InnoDB 在悲观事务(锁)方面的差异,参见 与 MySQL InnoDB 的差异。