TiDB和MySQL的不兼容点
文章目录
- 镜像
- Tidb8
- mysql8
- 查询sql(json相关)
- 增改sql
- 建表语句
紧接上文(https://blog.csdn.net/2303_80236475/article/details/153642203?spm=1001.2014.3001.5502),这里介绍到底哪里不兼容。
这里使用的docker来安装mysql和tidb的环境,但无所谓,只要能用就行
镜像
Tidb8
docker pull pingcap/tidb:v8.5.0docker run -d --name tidb-v8 -p 4000:4000 -p 10080:10080 -e TIDB_CONFIG="log.level=info" pingcap/tidb:v8.5.0
- -d:让容器在后台运行,不占用当前 CMD 窗口。
- –name tidb-v8:给容器命名为 “tidb-v8”,后续管理(如停止、删除)可直接用这个名称。
- -p 4000:4000:将容器的 4000 端口(TiDB 客户端连接端口)映射到本地 4000 端口,用于连接数据库。
- -p 10080:10080:将容器的 10080 端口(TiDB 状态监控端口)映射到本地 10080 端口,可通过浏览器访问
http://127.0.0.1:10080
查看状态。 - -e TIDB_CONFIG=“log.level=info”:设置环境变量,将 TiDB 日志级别设为 “info”,便于查看基础运行日志。
- pingcap/tidb:v8.5.0:指定使用 TiDB 8.5.0 版本的官方镜像(LTS 稳定版)。
mysql8
uv pip show langgraph-checkpoint-mysqldocker run -d --name mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
-d
:后台运行容器;--name mysql8
:给容器命名为mysql8
,方便后续操作;-p 3306:3306
:将容器的 3306 端口映射到主机的 3306 端口(主机端口:容器端口);- -e配置环境变量:
MYSQL_ROOT_PASSWORD
:设置 root 用户密码(需替换为你自己的密码,如123456
);
- 末尾参数
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
:设置数据库默认字符集为 UTF8mb4,避免中文乱码。
查询sql(json相关)
核心差异
JSON_TABLE
功能:TiDB 对JSON_TABLE
的支持较弱,尤其不支持用JSON_KEYS
或动态 JSON 路径作为输入(MySQL 完全支持)。- 动态 JSON 解析:TiDB 对
JSON_EXTRACT
结合CONCAT
生成的动态路径处理能力有限,可能导致提取失败。
建个简单的user表,插入两条数据,用相同的sql查询数据
CREATE TABLE users (id INT PRIMARY KEY,info JSON NOT NULL -- 存储用户的动态属性(如爱好、联系方式)
);INSERT INTO users (id, info) VALUES
(1, '{"name": "Alice", "hobbies": ["reading", "hiking"], "contacts": {"email": "alice@test.com", "phone": "123456"}}'),
(2, '{"name": "Bob", "hobbies": ["gaming"], "contacts": {"phone": "654321"}}');
测试 1:用 JSON_TABLE
解析数组( hobbies 字段)
SELECT u.id,jt.hobby
FROM users u,JSON_TABLE(u.info -> '$.hobbies', -- 解析 JSON 数组'$[*]' COLUMNS (hobby VARCHAR(50) PATH '$')) AS jt;
测试 2:动态提取 JSON 字段( contacts 中的任意键)
SELECT u.id,jt.contact_key,JSON_UNQUOTE(JSON_EXTRACT(u.info, CONCAT('$.contacts.', jt.contact_key))) AS contact_value
FROM users u,JSON_TABLE(JSON_KEYS(u.info -> '$.contacts'), -- 动态获取 contacts 的所有键'$[*]' COLUMNS (contact_key VARCHAR(50) PATH '$')) AS jt;
测试 3:JSON 聚合函数(合并所有爱好)
SELECT JSON_ARRAYAGG(JSON_UNQUOTE(hobby)) AS all_hobbies
FROM users u,JSON_TABLE(u.info -> '$.hobbies','$[*]' COLUMNS (hobby VARCHAR(50) PATH '$')) AS jt;
增改sql
核心不兼容点
AS new
表别名:MySQL 支持给插入的新记录起别名(如 AS new
),并在 ON DUPLICATE KEY UPDATE
中用 new.字段
引用新值;TiDB 不支持该语法,会直接报语法错误。
CREATE TABLE products (id INT PRIMARY KEY, -- 主键,唯一标识商品name VARCHAR(100) NOT NULL,price DECIMAL(10, 2) NOT NULL
);
INSERT INTO products (id, name, price) VALUES (1, '笔记本电脑', 5000.00);
测试 UPSERT 语句
用类似 UPSERT_CHECKPOINTS_SQL
的逻辑,尝试插入一条可能冲突的记录(id=1
已存在),并在冲突时更新价格
建表语句
核心不兼容点
1. 生成列语法 AS (UNHEX(MD5(checkpoint_ns))) STORED
MySQL 支持 STORED
生成列(物理存储计算结果),TiDB 不支持通过 ALTER TABLE
语句添加存储型生成列(STORED
类型的生成列)。
2. 修改主键(DROP PRIMARY KEY
+ ADD PRIMARY KEY
)
TiDB 对主键的修改(尤其是删除后重新添加)的兼容性和性能表现与 MySQL 不同,在 TiDB 中,表默认使用聚簇索引(主键即聚簇索引),这种情况下直接执行 DROP PRIMARY KEY
操作是不被允许的。当表使用聚簇索引时,不支持删除主键。
生成列语法 AS (UNHEX(MD5(checkpoint_ns))) STORED
验证
CREATE TABLE test_table (id INT PRIMARY KEY,name VARCHAR(100) NOT NULL
);
-- 模拟 MySQL 分支的生成列语法
ALTER TABLE test_table
ADD COLUMN name_hash BINARY(16) AS (UNHEX(MD5(name))) STORED,
DROP PRIMARY KEY,
ADD PRIMARY KEY (id, name_hash);
主键修改验证
CREATE TABLE test_table (id INT PRIMARY KEY,name VARCHAR(100) NOT NULL
);
-- 执行迁移语句(添加生成列):
ALTER TABLE test_table
ADD COLUMN name_hash BINARY(16) AS (UNHEX(MD5(name))) STORED,
DROP PRIMARY KEY,
ADD PRIMARY KEY (id, name_hash);