TiDB 学习笔记

  1. 我为什么去学 TiDB
    背景很简单:公司一个业务表涨到快 2000 万行,单机 MySQL 已经开始"喘"——加索引锁半天、分库分表又没人愿意维护、读写分离延迟还经常闹心。
    听同事说 TiDB “兼容 MySQL、还能水平扩展、不用分库分表”,我第一反应是:这不就是白嫖版 MySQL 集群吗? 结果真上手才发现,它确实能省掉分库分表,但和 MySQL 不是一回事,用"MySQL 直觉"去用,分分钟踩坑。
    这篇笔记就记录我从一个 docker pull 都嫌麻烦的人,到能本地起集群、跑通迁移、踩中热点的全过程。
  2. TiDB 到底是什么(我的白话版)
    一句话:TiDB 是一个"假装自己是 MySQL、但底下是分布式 KV 存储"的开源数据库。
    它对外说 MySQL 协议(你的应用、ORM、Navicat 基本都能直连),对内其实把数据切成一片片(叫 Region),分散存在一堆存储节点(TiKV)上,每个 Region 存三份、靠 Raft 保证不丢。中间有个"大脑"(PD)负责调度和发时间戳。
    所以它解决的真实问题是:单机 MySQL 撞到分库分表天花板时,不想自己维护分片逻辑的团队,可以用 TiDB 平滑顶上去。
    一句话先钉死:协议兼容 ≠ 引擎相同。 TiDB 没有 InnoDB。后面所有坑都源于这句话。
  3. 最快上手:用 TiUP 起一个本地集群
    官方给了一键体验工具 TiUP,本地起个假集群(playground)只要几条命令,不用 Docker、不用自己配。

装 TiUP(Mac / Linux 通用)

curl --proto ‘=https’ --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh

让 tiup 命令生效(按它装完的提示 source 一下)

source ~/.bashrc # 或 ~/.zshrc

起一个本地 playground(1 个 TiDB + 3 个 TiKV + 3 个 PD 的迷你集群)

tiup playground v8.5.6 --tag mylearn

另开一个终端,连进去(和连 MySQL 一模一样)

mysql -h 127.0.0.1 -P 4000 -u root
连上之后 SELECT VERSION(); 会返回类似 8.0.11-TiDB-v8.5.6,看到 TiDB 字样就说明通了。
踩坑提醒:playground 是内存级玩具,进程一关数据全没。别往里导生产数据,它就用来"试语法、看行为"。我第一次就没注意,导了半天才发现重启全空了 :sweat_smile:
想认真点,可以用 tiup playground 加 --db 2 --kv 3 --pd 3 模拟多节点;真要上生产,得用 tiup cluster 走离线部署 + 拓扑文件,那是另一篇笔记的事了。
3. 架构四件套,用"公司部门"来记
组件
类比
干什么
存不存数据
TiDB Server
前台接待
接收 SQL、解析优化、生成分布式执行计划
不存(无状态)
TiKV
档案室(行存)
真正存数据的存储节点,RocksDB 打底

PD
行政大脑
元数据、调度 Region、发全局时间戳 TSO
存元数据
TiFlash
数据分析部(列存)
列式副本,给分析查询加速
存(副本)
我的理解窍门:TiDB 层只负责"翻译 SQL",真正的数据在 TiKV 的 KV 里。所以你能无限水平加 TiDB 节点扛连接,但"数据量"取决于 TiKV。
Region 是核心概念:数据按 Key 范围切成一片片,默认一片约 96MB,太大就自动分裂,太小就合并,全由 PD 自动调度——这才是"不用分库分表"的来源。你啥都不用管,它自己搬。
4. 踩坑第一弹:AUTO_INCREMENT 写入热点(血泪)
这是我学的第一个、也是最痛的一个坑。
直觉写法,建表用自增主键:
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
amount DECIMAL(10,2),
created_at DATETIME
);
然后狂写订单。结果监控一看:集群里只有一个 TiKV 节点 CPU 拉满,其他节点在摸鱼。
原因:自增主键是单调递增的,所有新写入的 Key 都比之前的大,于是全砸向"最后一个 Region"。水平扩展的优势直接被废——这就是写入热点。
解法(二选一):
– 方案 A:AUTO_RANDOM,把主键打散到不同 Region
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_RANDOM,

);

– 方案 B:显式分片行 ID(适合不想改主键类型的场景)
CREATE TABLE orders (
id BIGINT PRIMARY KEY,

) SHARD_ROW_ID_BITS = 4;
经验:凡是"写多、主键自增"的表,上线前先想热点。这个坑在 MySQL 里不存在(单机嘛),但到了 TiDB 是必考题。
5. 事务与隔离级别:和 MySQL 的微妙差异
TiDB 的事务模型源自 Google Percolator,靠 MVCC(多版本) + 两阶段提交实现。
默认隔离级别是 Repeatable Read,但细节和 InnoDB 不完全一致,别想当然等同;
早期默认乐观事务(提交才检测冲突,冲突要应用层重试),现在默认悲观事务,用起来更像 MySQL;
每次事务都要从 PD 拿全局时间戳(TSO)。这点很关键:PD 离 TiDB 越近越好,跨地域部署时 PD 延迟会直接加到事务延迟上。
我验证过的小实验:
– 会话 A
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

– 会话 B(另一个终端,不提交也能读到旧值,MVCC 生效)
SELECT balance FROM accounts WHERE id = 1; – 看到的是事务开始前的快照

– 会话 A
COMMIT;
– 会话 B 再次查询才会看到新值(RR 隔离下本事务内不变)
理解 MVCC 之后,“为什么 TiDB 读不阻塞写、写不阻塞读"就通了——本质是读旧版本。
6. 从 MySQL 迁移的兼容性边界
这是最多人翻车的地方。官方说"兼容 MySQL 5.7 / 8.0”,但请务必理解两层:
:white_check_mark: 真的兼容的:
网络协议、大部分 SQL 语法;
应用层基本零改(MyBatis / JPA / 原生驱动);
常用函数、JOIN、子查询。
:warning: 不兼容 / 要小心的:
没有 InnoDB:存储引擎相关行为、个别 Optimizer Hint、部分函数表现不同;
外键到 v6.6.0(2023) 才支持,老版本想都别想;
自增热点(见第 4 节);
某些 MySQL 独有语法/存储过程特性不支持。
我的迁移建议清单:
先用 tidb-lightning 或 dumpling 把结构 + 数据导过来;
跑一遍业务核心 SQL,重点看执行计划(EXPLAIN ANALYZE)和 MySQL 差异;
检查所有自增主键表,改 AUTO_RANDOM;
别指望 100% 原地替换——官方原话就是 “It is not MySQL/InnoDB”。
7. HTAP 初体验:TiFlash 真能"一套库又跑事务又跑分析"?
HTAP 是 TiDB 的卖点之一:同一套数据,事务和分析一起跑。
原理我记成一句话:TiFlash 是 TiKV 的"列存镜像",通过 Raft Learner 异步同步,分析查询跑在独立节点,不拖慢交易。
实操:给某张表加列存副本,分析查询就能自动走 TiFlash。
– 给 orders 表加 2 个 TiFlash 副本
ALTER TABLE orders SET TIFLASH REPLICA 2;

– 看副本状态(看到可用再跑分析)
SELECT * FROM information_schema.tiflash_replica WHERE table_name = ‘orders’;

– 一条"分析型"查询,优化器会自动判断是否走列存
SELECT user_id, SUM(amount) FROM orders GROUP BY user_id ORDER BY 2 DESC LIMIT 10;
体验结论:
真能跑,一份数据不用 ETL 到数仓就能做实时分析,这点很爽;
代价是存储翻倍 + 额外节点,所以别"全表都加 TiFlash 副本",只给真跑分析的表加;
小数据量下收益不明显,等数据真上亿、又要实时看报表时,它的价值才出来。
8. 我的学习资源清单(亲测有用)
官方文档(docs.pingcap.com)—— 虽然是英文为主,但最权威,迁移前必读;
TiUP playground —— 比看十篇博客都管用,动手能力直接拉满;
TiDB Dashboard(playground 起好后 http://127.0.0.1:2379/dashboard)—— 看慢查询、热点 Region、执行计划,可视化学习神器;
AskTUG 社区(asktug.com)—— 国内 TiDB 问答最活跃的地方,踩坑先搜这里;
Jepsen 报告(2019) —— 不是入门必读,但想理解"一个数据库靠不靠谱看它怎么认错",这篇是必修课(PingCAP 当年公开把问题全修了,反而圈粉)。
9. 结语:学完我记住的三句话
TiDB 不是 MySQL,是"说 MySQL 话的分布式数据库"。 用 MySQL 直觉去用,必踩坑(尤其是热点)。
水平扩展省的是"分库分表",不是"思考"。 Region 自动调度很香,但主键设计、副本策略、PD 位置这些,还是得人来想。
先 playground 玩熟,再谈迁移。 本地起个集群只要 5 分钟,但能帮你避开 90% 的线上事故。
学 TiDB 最大的收获,不是学会了一个数据库,而是被迫搞懂了"分布式"到底意味着什么——一致性和性能,从来都是要取舍的。