预见猿份
主题
首页面试题模拟面试SQL练习在线工具关于我们老苗一对一私教学员评价
实战项目
零基础学习路线项目前置基础创新WMS项目Java微服务框架与实战云岚到家项目闪聚支付项目学成在线项目青橙电商项目JVM原理与实战调优分布式事务专题Java高频面试题MySQL从入门到精通达梦数据库从入门到实战MongoDB从入门到实战PostgreSQL从入门到实战TiDB从入门到实战Java数据结构与算法Java 并发编程(JUC)实战课程老苗一对一私教学员评价
blog我的会员
  • TiDB从入门到实战|做过分库分表的Java程序员的分布式SQL课程

    • 课程介绍
    • 第1章 认识TiDB与整体架构
    • 第2章 MySQL兼容性与差异清单
    • 第3章 TiDB vs 分库分表全面对比
    • 第4章 数据建模与分布式特性
    • 第5章 Java集成实战
    • 第6章 HTAP、执行计划与调优
    • 第7章 迁移与日常运维







----- 到底线了 -----

第1章 认识 TiDB 与整体架构 ​

🎯 本章学习目标 ​

  1. 说清 TiDB 的定位:它不是「另一个 MySQL」,而是替代「MySQL + 分库分表中间件 + 一堆周边运维工具」的一整套分布式 SQL 方案,对上层仍暴露 MySQL 协议。
  2. 建立计算存储分离的架构心智,讲清四大组件职责:TiDB Server(无状态 SQL 层)、PD(元信息 + 调度 + 全局时钟 TSO)、TiKV(分布式行存,Region 多副本)、TiFlash(列存,HTAP 分析加速)。
  3. 理解 TiDB 如何天生免掉分库分表:数据按 Key Range 自动切成 Region(默认约 96MB 触发分裂)、自动打散到多 TiKV 节点、多副本 Raft 强一致、扩缩容对应用透明。
  4. 记住几个「连接层」关键事实:默认端口 4000(不是 3306)、MySQL 协议兼容、可直接用 MySQL 的 Java 驱动与 Navicat/DBeaver 等工具。
  5. 用 tiup playground 一条命令在本地拉起一个体验集群,并用 mysql 客户端与 Java(MySQL Connector/J) 各连一次,打印版本。

1.1 从「分库分表的痛」说起:TiDB 解决什么问题 ​

你在 云岚到家第九章 里做过这样的事:订单表数据量上来后,用 ShardingSphere-JDBC 把它按用户 ID 取模拆成「4 库 × 若干表」,并且——

  • 写业务代码时时刻记着分片键,查询不带 user_id 就要广播到所有分片再内存归并;
  • 主键不能再用单库自增,得上雪花算法/号段造全局 ID;
  • 跨库的 JOIN、GROUP BY、分页、事务要么受限要么要额外处理;
  • 数据涨到要加机器时,面临 rebalance:新节点搬数据、灰度双写、一致性校验,一轮下来脱层皮;
  • 一次 ALTER TABLE ADD COLUMN 要在几十张物理表上逐个执行。

这些复杂度,本质都来自「把一张逻辑表人为拆成 N 张物理表,再靠中间件在应用侧兜住拆分逻辑」。

TiDB 换了一个思路:让「一张表」在底层就自然是分布式的。你不拆表,数据自己按范围切成 Region、自己分散到多台存储节点、自己用 Raft 保持多副本一致、自己在线扩缩容。应用看到的还是一个 MySQL 样的库、一张表、一条普通 SQL——分库分表中间件替你操心的那些事,下沉到了数据库内核里自动化完成。

你在分库分表里做的在 TiDB 里变成
选分片键、写路由规则无需分片键,数据自动按 RowID/主键切 Region
全局 ID 方案(雪花/号段)普通自增 / AUTO_RANDOM,TiDB 内部分配
应用/中间件处理跨库 JOIN、聚合一条标准 SQL,引擎层分布式执行
加机器要做 rebalance、双写迁移加 TiKV 节点,PD 自动搬 Region,对应用透明
DDL 铺到 N 张物理表一条 ALTER TABLE,在线异步执行一次搞定

一句话:分库分表是「把分布式复杂度甩给开发和运维」,TiDB 是「把分布式复杂度关进数据库内核」。 本课程的主线就是带你完成这次「责任转移」的认知切换。

1.2 整体架构:计算与存储分离的四大组件 ​

逐个组件用 MySQL/分库分表的语言解释:

1.2.1 TiDB Server(计算层) ​

  • 干的事:接收 MySQL 协议的连接和 SQL,做解析 → 优化 → 生成分布式执行计划,再向 TiKV/TiFlash 取数据、汇总返回。
  • 无状态:它不存数据,所以可以随意起多个实例,前面挂个 LB 做接入均衡;某个 TiDB 挂了,客户端重连到别的即可。
  • 对应分库分表世界:它就像「ShardingSphere 中间件 + MySQL Server」合体,只不过这个「中间件」是数据库官方内核,能力远强于外挂中间件(能下推、能跨分片事务、能并行执行)。

1.2.2 PD(Placement Driver,大脑) ​

  • 三件事:① 存元信息(哪个 Region 的副本在哪些 TiKV 上);② 调度(热点 Region 迁移、副本均衡、故障补副本);③ 分配 TSO(全局单调递增的时间戳,用于分布式事务的快照读与冲突检测)。
  • 本身高可用(Raft,建议奇数节点)。
  • 对应分库分表世界:它承担了「注册中心 + 配置中心 + 全局发号器 + 再平衡调度器」的角色,而且是自动的——你分库分表里手写/运维的那套,PD 内核全包了。

1.2.3 TiKV(行存层,事务数据的家) ​

  • 分布式 Key-Value 存储,底层每个节点用 RocksDB。数据的基本单位是 Region:一段连续的 Key Range(默认约 96MB 触发分裂、144MB 强制分裂),一个 Region 的多副本(默认 3 副本)分散在不同 TiKV 节点上,用 Multi-Raft 协议保证强一致——多数派写成功事务才提交。
  • 这就是 TiDB「天生分布式」的根基:你的「一张大表」在 TiKV 里早就被切成无数个 Region 散在集群里了,根本不需要你分库分表。
  • 对应分库分表世界:Region ≈ 你拆出来的「分片/物理表」,但它是自动切、自动搬、自动多副本的,对你完全透明。

1.2.4 TiFlash(列存层,分析加速器,可选) ​

  • 一类特殊存储节点:把 TiKV 的数据以列式再存一份副本(通过 Raft Learner 异步但实时同步),专门加速 OLAP 大宽表扫描/聚合。
  • 有了它,同一份数据既能走 TiKV 做事务(OLTP),又能走 TiFlash 做分析(OLAP)——这就是 HTAP,省掉「业务库 + 抽数到数仓」的链路。
  • 对应分库分表世界:以前你在分库分表上跑复杂报表要拖垮所有分片,要么另建数仓;TiDB 用 TiFlash 原生解决(第 6 章详解)。

1.3 关键事实:连接层的「MySQL 味」 ​

对 Java 程序员而言,最重要的一条是:连 TiDB 基本等于连 MySQL。

维度MySQLTiDB
默认端口33064000
通信协议MySQL 协议兼容 MySQL 协议
Java 驱动com.mysql.cj.jdbc.Driver同一个,照用(也可用 MariaDB 驱动)
GUI 工具Navicat/Workbench/DBeaver都适用(填端口 4000 即可)
命令行mysql -uroot -pmysql -h -P 4000 -uroot -p(用同款客户端)
SQL 方言MySQL 5.7/8.0兼容常用语法(差异见第 2 章)
生态工具mysqldump/MyBatis...多数可用(迁移与备份有 TiDB 专用工具,第 7 章)

注意端口这个最常见的坑:很多人按 3306 连 TiDB 连不上——TiDB Server 的 SQL 端口是 4000,另外 PD 默认 2379、TiKV 默认 20160。做实验记牢 4000。

1.4 起一个本地体验集群:tiup playground ​

官方集群管理工具 tiup 把装 TiDB 变成一条命令。先装 tiup,再起一个最小拓扑的体验集群:

bash
# 安装 tiup(Linux/macOS)
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.bash_profile          # 使 tiup 进入 PATH

# 一条命令拉起单机体验集群(TiDB+PD+TiKV+TiFlash 各跑在本机)
tiup playground v8.5.0 --tiflash 1
1
2
3
4
5
6

两个常用变体:想知道能填哪些版本号,先跑 tiup list tidb;playground 默认退出即清空数据,想下次接着用同一个集群,加 --tag:tiup --tag tidbdemo playground v8.5.0 --tiflash 1(本章课后练习里有「重启 TiDB 观察自增跳号」一题,必须靠 --tag 才能保住数据)。

启动成功后,输出里会直接告诉你怎么连(每行都是 tiup 的真实回显,记住端口 4000):

log
Starting component `playground`: ...
TiDB PID 2149, Port 4000, Binary /home/tidb/.tiup/components/tidb/v8.5.0/tidb-server
TiKV PID 2173, Port 20160, Binary /home/tidb/.tiup/components/tikv/v8.5.0/tikv-server
PD PID 2158, Port 2379, Binary /home/tidb/.tiup/components/pd/v8.5.0/pd-server

CLUSTER START SUCCESSFULLY, Enjoy it ^-^
To connect TiDB:     mysql --comment --host 127.0.0.1 --port 4000 -u root -p (no password)
To view the dashboard:  http://127.0.0.1:2379/dashboard
PD client endpoints: [127.0.0.1:2379]
To view the Prometheus: http://127.0.0.1:9090
To view the Grafana:    http://127.0.0.1:3000
1
2
3
4
5
6
7
8
9
10
11

用 mysql 客户端连上后跑三条确认:

sql
SELECT version();               -- 形如 8.0.11-TiDB-v8.5.0:前缀是它冒充的 MySQL 版本,后才是 TiDB 真版本
SELECT tidb_version()\G         -- 完整构建信息(Release Version / Git Branch / 编译时间)
SHOW COMPONENTS;                -- 看集群里 PD/TiDB/TiKV/TiFlash 各自的地址与版本
SHOW STORES;                    -- 看存储节点(TiKV)的容量、Region 数、Leader 分布
1
2
3
4

playground 只用于学习

tiup playground 是为「本地体验/写代码」设计的,所有进程在一台机器上、副本不齐全、没有容灾。生产环境必须用 tiup cluster 按真实拓扑部署(第 7 章),切勿把 playground 直接上生产。

1.4.1 Windows / 无 Linux 环境 ​

TiDB Server 只出 Linux 二进制,tiup 也不支持 Windows,所以 Windows 上做实验有四条路,按「能做到的事」从多到少排:

方案怎么起能做到做不到
① WSL2 里装 tiup(推荐)wsl --install 后进 Ubuntu,照 1.4 的 Linux 命令装 tiup全套:playground、Dashboard、Grafana、Lightning/BR、多 TiDB 实例磁盘 IO 比原生 Linux 慢一些
② Docker 跑单容器docker run -d -p 4000:4000 pingcap/tidb:latest只跑 SQL 层(存储用进程内的 mock-tikv,数据不落盘)没有 Region/热点/TiFlash/BR,第 4、6、7 章的实验全做不了
③ TiDB Cloud Serverless(免费)邮箱注册 tidbcloud.com/free-trial 建 Serverless 集群,Connect 面板拿 host/端口/用户名/密码所有纯 SQL 实验 + Java 连接;MySQL 协议,端口通常是 443碰不到集群内部(Dashboard、Region、BR、tiup)
④ TiDB Labs 在线实验室浏览器打开 labs.pingcap.com 选一个教程沙箱免安装体验 Dashboard、Lightning、TiCDC 等环境是别人编排好的,不能自定义拓扑

选路原则:只要你想做完第 4/6/7 章(Region、热点、TiFlash、备份、扩缩容),必须走 ①;只想验证「MySQL 驱动能不能连、SQL 行为对不对」,走 ③ 最省事。本课程后面每章答案里都会标出该题需要 ①②③ 中的哪一种。

1.5 跑通第一个 Java 连接 ​

关键:依赖、驱动类、连接串都用 MySQL 那一套,只是端口换成 4000。

xml
<!-- pom.xml:就是普通 MySQL 驱动,TiDB 不需要专用驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.3.0</version>
</dependency>
1
2
3
4
5
6
java
import java.sql.*;

public class TidbFirstConnect {
    public static void main(String[] args) throws Exception {
        // 和连 MySQL 唯一明显的区别:端口是 4000
        String url = "jdbc:mysql://127.0.0.1:4000/test"
                   + "?useSSL=false&serverTimezone=UTC&characterEncoding=utf8";
        String user = "root";
        String pwd = "";                       // playground 默认 root 无密码

        try (Connection conn = DriverManager.getConnection(url, user, pwd);
             Statement st = conn.createStatement()) {

            // 建一张表(AUTO_RANDOM 主键,第 4 章细讲),再查版本确认连的是 TiDB 而不是 MySQL
            st.execute("CREATE TABLE IF NOT EXISTS demo(id bigint primary key auto_random, note varchar(50))");
            try (ResultSet rs = st.executeQuery("SELECT version(), current_database()")) {
                if (rs.next()) {
                    System.out.println("连上了 TiDB!版本:" + rs.getString(1));
                    System.out.println("当前库:" + rs.getString(2));
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

你会的 MySQL JDBC 编程模型(DriverManager/PreparedStatement/ResultSet)、连接池(HikariCP/Druid)、ORM(MyBatis/JPA)在 TiDB 上直接可用。第 5 章专门讲连接池参数与事务模式在 TiDB 上需要额外注意的点。

1.6 本章小结 ​

  1. TiDB 的定位:替代「MySQL + 分库分表中间件 + 运维工具链」的一体化分布式 SQL 数据库,上层仍说 MySQL 协议。
  2. 架构是计算存储分离:TiDB Server(无状态 SQL 层) + PD(元信息/调度/TSO 大脑) + TiKV(行存,Region 多副本 Raft) + TiFlash(列存,HTAP 分析,可选)。
  3. 免掉分库分表的根基:数据按 Region 自动切分、自动打散、自动多副本、在线扩缩容对应用透明——分片键、全局 ID、rebalance 这些你不用管了。
  4. 连接层照搬 MySQL,但默认端口 4000;Java 用 MySQL 驱动即可。
  5. 起集群:tiup playground(学习用),生产用 tiup cluster。

✏️ 课后练习 ​

  1. 用 tiup playground 起集群,mysql -P 4000 连上后执行 SHOW COMPONENTS; 和 SHOW STORES;,把各组件地址/端口抄下来,确认 SQL 端口是 4000。
  2. 把 1.5 的 Java Demo 跑通,并在连接串里故意把端口写成 3306,观察报错,体会「端口是最常见的第一坑」。
  3. 用 CREATE TABLE t(a int); 建表后用 SHOW CREATE TABLE t; 观察它的 SHARD_ROW_ID_BITS、PRE_SPLIT_REGIONS 等 TiDB 特有属性,并查出它的表 ID 与隐藏行 ID 列(为第 4 章埋钩子)。
  4. 打开浏览器访问 http://127.0.0.1:2379/dashboard,在 TiDB Dashboard 里找到「SQL 语句分析」,回看刚才你执行的 SQL——熟悉这个后续第 6/7 章反复用的可视化控制台。

📖 参考答案 ​

本章 4 题都是「环境 + 观察」类。四题都能在 1.4.1 的方案①(WSL2 + tiup playground) 上完整做完;方案②③只能做第 2、3 题(没有 Dashboard、没有真 TiKV)。下面所有回显都是 v8.5.x playground 的实测形态,PID、时间、Region 数这类数字一定以你本机为准,但「哪一行有值、端口是多少、报错原文是什么」这些结构不会变,那才是本题要对账的东西。

第 1 题:起集群,用 SHOW COMPONENTS / SHOW STORES 抄下各组件地址端口,确认 SQL 端口是 4000

第 1 步,装 tiup(Ubuntu/WSL2 内执行,脚本会把 tiup 写进 ~/.tiup/bin 并改 PATH):

bash
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.bash_profile          # 或 source ~/.profile,让当前 shell 认识 tiup
tiup --version                  # 有版本号即安装成功
tiup list tidb | tail -5        # 看能起哪些 TiDB 版本,挑一个 LTS(本课程用 v8.5.0)
1
2
3
4

第 2 步,起集群(加 --tag,否则下次重启数据就没了,第 2 章跳号实验要用它):

bash
tiup --tag tidbdemo playground v8.5.0 --tiflash 1
1

回显逐行解读(这就是本题要抄的东西):

log
TiDB PID 2149, Port 4000, Binary /home/tidb/.tiup/components/tidb/v8.5.0/tidb-server
TiKV PID 2173, Port 20160, Binary /home/tidb/.tiup/components/tikv/v8.5.0/tikv-server
PD PID 2158, Port 2379, Binary /home/tidb/.tiup/components/pd/v8.5.0/pd-server

CLUSTER START SUCCESSFULLY, Enjoy it ^-^
To connect TiDB:     mysql --comment --host 127.0.0.1 --port 4000 -u root -p (no password)
To view the dashboard:  http://127.0.0.1:2379/dashboard
1
2
3
4
5
6
7

第 3 步,连上去。tiup 不带 mysql 客户端,所以三条路选一条:

bash
sudo apt install -y mysql-client-core-8.0        # WSL2/Ubuntu 里最省事的一个包装完就有 mysql 命令
mysql --comment --host 127.0.0.1 --port 4000 -u root      # root 无密码,直接回车进去
# 或者:Windows 上的 Navicat / DBeaver / MySQL Workbench 新建连接,主机填 WSL 的 IP、端口填 4000
#   WSL 的 IP 用 `hostname -I` 查;只填 127.0.0.1 在老版本 WSL2 上连不通(要做端口转发)
# 或者:连 TiDB Cloud Serverless,端口通常是 443 而不是 4000,且必须加 --ssl 与 --enable-cleartext-plugin
1
2
3
4
5

第 4 步,SHOW COMPONENTS; —— 一条命令看全集群角色。playground 单机的预期是 4 行(tidb / pd / tikv / tiflash),版本一致、地址都是 127.0.0.1:

text
+---------+-----------+-------+-----------------+-----------------+---------------------+-------------+
| NAME    | IP        | PORT  | HTTP_ADDR       | GRPC_ADDR       | START_TIME          | VERSION     |
+---------+-----------+-------+-----------------+-----------------+---------------------+-------------+
| tidb    | 127.0.0.1 |  4000 | 127.0.0.1:10080 |                 | 2026-10-02 14:03:11 | v8.5.0      |
| pd      | 127.0.0.1 |  2379 | 127.0.0.1:2379  |                 | 2026-10-02 14:03:08 | v8.5.0      |
| tikv    | 127.0.0.1 | 20160 | 127.0.0.1:20180 | 127.0.0.1:20160 | 2026-10-02 14:03:10 | 8.5.0       |
| tiflash | 127.0.0.1 |  3930 | 127.0.0.1:8234  | 127.0.0.1:3930  | 2026-10-02 14:03:14 | v8.5.0      |
+---------+-----------+-------+-----------------+-----------------+---------------------+-------------+
4 rows in set (0.01 sec)
1
2
3
4
5
6
7
8
9

读表三个要点:① PORT 列里 4000 就是本题要找的 SQL 端口;② tidb 的 HTTP_ADDR:10080 是它的状态/指标端口(curl 127.0.0.1:10080/status 可看);③ TiKV 的 VERSION 显示成 8.5.0(没有 v 前缀)是正常的,两个组件的版本字符串格式本就不同。不同小版本这里还会多出 DEPLOY_PATH、PARENT_ADDR 等列,以你实测为准。

第 5 步,SHOW STORES; —— 看存储节点。playground 只有 1 个 TiKV,所以只有一行:

sql
-- 先看精简版(列少、好抄):容量 / 剩余 / 磁盘使用率 / 版本
SELECT store_id, address, capacity, available, disk_usage, version
  FROM information_schema.tikv_store_status;
-- store_id | address           | capacity | available | disk_usage | version
-- -------- + ----------------- + -------- + --------- + ---------- + -------
--        1 | 127.0.0.1:20160   | 500GiB   | 480GiB    | 0.04       | 8.5.0

-- 再看 Region 分布与角色(本题真正要抄的是 TOTAL_REGION_COUNT)
SHOW STORES STATS;
1
2
3
4
5
6
7
8
9

第 6 步,把端口表背下来(后面每章都要用):

端口归属干什么谁会去连它
4000TiDB ServerMySQL 协议 SQL 入口你、驱动、Navicat
10080TiDB ServerHTTP 状态页 / /status、指标监控抓取、排障
2379PD客户端 API + Dashboard 入口 /dashboard应用取 TSO 不直连,但工具/浏览器要连
2380PD集群内 peer 通信仅 PD 之间
20160TiKVgRPC,TiDB 读写数据走这里TiDB / BR / pd-ctl
20180TiKV状态与指标 HTTP监控
3930 / 8123 / 8234TiFlash内部数据同步 / HTTP / 管理端口由集群内部使用
9090 / 3000Prometheus / Grafana监控与大盘(playground 会一起拉起)第 6、7 章

记法:应用只碰 4000;排障看 2379/dashboard;指标看 9090/3000;剩下的都是组件互连。

第 7 步,收尾(下次用 tiup --tag tidbdemo playground ... 数据还在;彻底清理):

bash
# Ctrl+C 停掉 playground(前台进程),再执行:
tiup clean --all
1
2

常见坑:

现象根因处理
按 3306 连,Connection refusedTiDB 的 SQL 端口是 4000改端口,这是新手第一坑(第 2 题专门复现它)
SHOW COMPONENTS 里没有 tiflash 行起集群时没带 --tiflash 1,或用了 mock-tikv 的单容器镜像重新 tiup playground v8.5.0 --tiflash 1
SHOW STORES 一行都没有你用的是 1.4.1 方案②的 Docker 单容器(pingcap/tidb 镜像内嵌 mock-tikv,没有真 TiKV)只能做 SQL 实验;要看 Region/存储必须走方案①
playground 每次起来都是空库没加 --tagtiup --tag tidbdemo playground ...

第 2 题:跑通 1.5 的 Java Demo,并把端口写成 3306 观察报错

第 1 步,备一个驱动 jar(不建 Maven 工程也能跑,最小路径):

bash
mvn dependency:get -Dartifact=com.mysql:mysql-connector-j:8.3.0
# WSL/Linux 下复制到当前目录
cp ~/.m2/repository/com/mysql/mysql-connector-j/8.3.0/mysql-connector-j-8.3.0.jar ./
# Windows PowerShell 下用:
#   Copy-Item $env:USERPROFILE\.m2\repository\com\mysql\mysql-connector-j\8.3.0\mysql-connector-j-8.3.0.jar .\
1
2
3
4
5

第 2 步,把 1.5 的 TidbFirstConnect.java 原文保存好,编译并运行(JDK 17+ 可直接单文件运行):

bash
java -cp .:mysql-connector-j-8.3.0.jar TidbFirstConnect.java     # Linux/WSL 用 : 分隔
java -cp .;mysql-connector-j-8.3.0.jar TidbFirstConnect.java     # Windows 用 ; 分隔
1
2

第 3 步,正确的预期输出(两行,注意版本号里一定带 -TiDB-):

text
连上了 TiDB!版本:8.0.11-TiDB-v8.5.0
当前库:test
1
2

两个观察点:① version() 返回的是 8.0.11-TiDB-vX.Y.Z 这种拼接串——8.0.11 是 TiDB 对外声称的 MySQL 兼容版本,v8.5.0 才是真身;② playground 自带一个 test 库且 root 无需密码,所以 current_database() 就是 test。

第 4 步,故意把 URL 端口改成 3306,再跑一次。分两种情况,两种都是本题要记的报错原文:

java
String url = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf8";
1

情况 A(本机没跑 MySQL,最常见)——TCP 层就被拒,报错里没有任何 SQL 语义:

text
Exception in thread "main" com.mysql.cj.jdbc.exceptions.CommunicationsException:
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago.
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
Caused by: java.net.ConnectException: Connection refused
    at java.base/sun.nio.ch.Net.connect0(Native Method)
1
2
3
4
5
6

情况 B(本机真有一个 MySQL 在 3306 上)——连上了,但连错了数据库,这才是更阴的坑:

text
连上了 TiDB!版本:8.0.35        ← 注意:没有 -TiDB- 字样,说明连的是真 MySQL
Exception in thread "main" java.sql.SQLSyntaxErrorException: Unknown database 'test'
  -- 或者库碰巧存在时:建表成功,但后面的实验全部对不上账
1
2
3

第 5 步,把这条自检固化成一行断言(以后所有 TiDB 工程启动时都值得打一次):

java
try (ResultSet rs = st.executeQuery("SELECT version()")) {
    rs.next();
    String v = rs.getString(1);
    if (!v.contains("-TiDB-")) throw new IllegalStateException("连的不是 TiDB:" + v);
}
1
2
3
4
5
报错长相真实含义下一步查什么
Connection refused端口没人监听 / 集群没起先看 playground 那个终端还在不在跑,再到 WSL 里 `ss -lntp
Communications link failure 但无 refused中间被防火墙/LB 掐了云主机安全组、WSL2 的 Windows 防火墙入站规则
Unknown database 'test'端口对了、库不对(多半连到真 MySQL 了)看 version() 有没有 -TiDB-
Access denied for user 'root'@'...'连上了但账号/密码/来源不匹配TiDB Cloud 的用户名是 xxxx.root 这种形式,不是 root

第 3 题:建无主键表 t(a int),用 SHOW CREATE TABLE 观察 TiDB 特有属性,并查表 ID 与隐藏行 ID

第 1 步,建表并插三行:

sql
CREATE TABLE t(a int);
INSERT INTO t VALUES (10),(20),(30);
1
2

第 2 步,看建表语句(不是 SHOW TABLE t,TiDB 里没有这个命令,见本題末尾的坑表):

sql
SHOW CREATE TABLE t\G
1
text
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `a` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1
2
3
4
5

三个信息量都很高的细节:① 没有出现 SHARD_ROW_ID_BITS=、PRE_SPLIT_REGIONS=、AUTO_RANDOM_BASE=——说明它们都是「不写就不显示」的表级选项,默认关闭(AUTO_RANDOM_BASE 更是只有 AUTO_RANDOM 表才有);② COLLATE=utf8mb4_bin 印证了第 2 章说的「TiDB 默认排序规则区分大小写」;③ ENGINE=InnoDB 是兼容用的假字段,TiDB 里引擎永远是 TiKV,别按 MySQL 直觉去换引擎。

第 3 步,查它的表 ID 与 RowID 打散信息(第 4、6 章多次要用):

sql
SELECT table_name, tidb_table_id, tidb_row_id_sharding_info
  FROM information_schema.tables
 WHERE table_schema = DATABASE() AND table_name = 't';
-- table_name | tidb_table_id | tidb_row_id_sharding_info
-- -----------+---------------+--------------------------
--  t         |            85 |              ← 空:既没主键聚簇,也没设 SHARD_ROW_ID_BITS/AUTO_RANDOM
1
2
3
4
5
6

对照:建一张 AUTO_RANDOM 表再查同一列,就能看到值(第 4 章细讲):

sql
CREATE TABLE t_ar(id BIGINT PRIMARY KEY AUTO_RANDOM(5), b INT);
SHOW WARNINGS;                    -- 建 AUTO_RANDOM 表后紧跟着看这句,很有用
-- Level | Code | Message
-- ------+------+--------------------------------------------
-- Note  | 1105 | Available implicit allocation times: 288230376151711743

SELECT table_name, tidb_table_id, tidb_row_id_sharding_info
  FROM information_schema.tables WHERE table_name IN ('t','t_ar');
-- t     | 85 |                 ← 无主键:行靠隐藏的 _tidb_rowid 定位
-- t_ar  | 86 | PK_AUTO_RANDOM_BITS=5   ← 有主键且聚簇:handle 就是主键,分片位 5
1
2
3
4
5
6
7
8
9
10

第 4 步,把隐藏行 ID 「抓」出来——这是无主键表最直观的一张图:

sql
SELECT _tidb_rowid, a FROM t ORDER BY _tidb_rowid;
-- +--------------+----+
-- | _tidb_rowid  | a  |
-- +--------------+----+
-- |            1 | 10 |
-- |            2 | 20 |
-- |            3 | 30 |
-- +--------------+----+
SELECT _tidb_rowid, id FROM t_ar LIMIT 3;   -- ❌ ERROR 1105: column _tidb_rowid not found
1
2
3
4
5
6
7
8
9

最后一行报错很关键:有聚簇主键的表根本没有 _tidb_rowid(handle 已经是主键了),而无主键表的 _tidb_rowid 集中递增——这就是第 4 章写热点的两个根因之一。

第 5 步,顺手看 Region(有真 TiKV 才能看到,方案②会报错):

sql
SHOW TABLE t REGIONS;
-- REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS
-- --------- + --------- + ------- + --------- + --------------- + ----- + ---------- + ------------- + -------- + -------------------- + ---------------
--      5xxx | t_85_     |         |      5xxx |               1 | ...   |          0 |           ... |      ... |                    1 |              3
-- 一行就是「这张表现在只有一个 Region」(数据量没到 96MB),第 4 章 PRE_SPLIT_REGIONS 就是把这里变多行
1
2
3
4
5
错误写法为什么错正确写法
SHOW TABLE t;TiDB/MySQL 都没有这个命令,直接语法报错SHOW CREATE TABLE t\G
SHOW TABLES t;SHOW TABLES 不能接表名SHOW TABLES LIKE 't%';
SHOW TABLE t REGIONS; 当成看结构它看的是 Region 分布,不是表结构两个都要会,职责不同
DESC t; 里找 SHARD_ROW_ID_BITS它是表级选项,不在列信息里SHOW CREATE TABLE 或 information_schema.tables.tidb_row_id_sharding_info

第 4 题:打开 Dashboard,在「SQL 语句分析」里回看你执行过的 SQL

第 1 步,确认入口。playground 的 Dashboard 内嵌在 PD 里,无需密码:

text
http://127.0.0.1:2379/dashboard
# 浏览器在 Windows、集群在 WSL2 时:先试 WSL 的 IP(hostname -I 查),不行就在 WSL 里做转发:
#   socat TCP-LISTEN:2379,fork,reuseaddr TCP:127.0.0.1:2379   # 或用 Windows 端 Portproxy
# TiDB Cloud Serverless(方案③)没有这个地址,对应功能在控制台的 Developer → Insights
1
2
3
4

第 2 步,左侧菜单至少应有这几项(本题要用的标记出来了):

菜单英文名本课程什么时候用
语句分析 / SQL 语句分析Statements Analytics本题;第 6 章找 Top SQL
慢查询Slow Query第 6 章
键值分析 / 热力图Key Visualizer / Heatmap第 4 章验热点全靠它
任务管理 / DDLJobs / DDL第 2 章看在线 DDL 进度
拓扑 / 配置Topology / Configuration第 7 章看节点与改参数
资源管控Resource Control第 6 章资源组
SQL 性能诊断SQL Diagnosis第 6 章进阶

第 3 步,到「语句分析」里把刚才那几条 SQL 找回来。先故意制造负载再刷新(否则列表是空的):

sql
SELECT COUNT(*) FROM t;                       -- 跑 20 次(或者用下面的循环一次制造多条)
SELECT a FROM t WHERE a > 0 ORDER BY a DESC;  -- 带排序的,方便看 diff
1
2

列表预期(列名与排序可能随版本微调,但维度不变):

text
SQL 摘要           执行次数   平均执行时间   总执行时间   扫行数   内存   CPU 时间   SQL 延迟
SELECT `count`(...)     20      0.8 ms        16 ms      3       0       0.5 ms     0.7 ms
SELECT `a` FROM ...      1      1.2 ms        1.2 ms     3       0       0.9 ms     1.1 ms
1
2
3

第 4 步,点一行进去,把三个东西看完(这是第 6 章的预支):① 完整 SQL 样例(带真实参数);② 执行计划;③ 指标演进图(执行次数/延迟趋势)。试着把这里的计划与手动 EXPLAIN 的结果对一下,两边应该一致:

sql
EXPLAIN SELECT COUNT(*) FROM t;
-- id             | estRows | task      | access object | operator info
-- StreamAgg_9    | 1.00    | root      |               | funcs:count(Column#4)->Column#3
--  └─TableReader_10 | 1.00  | root      |               | data:StreamAgg_8
--    └─StreamAgg_8   | 1.00  | cop[tikv] |               | funcs:count(1)->Column#4
--      └─TableFullScan_7 | 3.00 | cop[tikv] | table:t  | keep order:false
-- 注意:没跑过 ANALYZE 的新表,estRows 常与真值差得很远(第 6 章细讲)
1
2
3
4
5
6
7

第 5 步,回到「拓扑」页确认第 1 题的结论:Dashboard 里能看到 1 个 TiDB、1 个 PD、1 个 TiKV、1 个 TiFlash,与 SHOW COMPONENTS 一致——以后忘了集群长什么样,先看拓扑再看大盘。

现象原因处理
访问 /dashboard 返回 404 或白屏连到了 10080(TiDB 的状态页)而不是 2379换 http://127.0.0.1:2379/dashboard
页面要登录集群开了 TLS + 客户端认证(生产常见)用部署时设的账号密码;若只配了 token,则用户名随意、密码填 authentication-token 的值
语句分析里空的统计窗口没覆盖到,或刚执行完未上报(默认每 60s 一个采样点)多点几次刷新;或先查 information_schema.statements_summary
想用命令而不是浏览器——SELECT digest_text, exec_count, avg_exec_time FROM information_schema.statements_summary ORDER BY avg_exec_time DESC LIMIT 5;(这就是「语句分析」背后的那张表,第 6 章重点用)
← 课程介绍第2章 MySQL兼容性与差异清单 →








如果发现文档内容有错误或排版错乱,请及时联系站长老苗修改,不胜感激。联系我们
关于我们 | 隐私政策 | 豫ICP备2026003386号-4 | 豫公网安备41010202004008号
目录

本页无章节