TiDB 是 PingCAP 开源的分布式 HTAP 数据库,既能像 MySQL 一样扛高并发 OLTP 事务,又能用同一份数据跑实时 OLAP 分析,彻底告别「业务库 + 数据仓库」双写同步的麻烦。当单实例 MySQL 在千万级写入和复杂报表面前开始力不从心时,TiDB 的弹性水平扩展与强一致事务就成了最顺手的升级路径。本文从架构、部署、迁移到调优,带你把一套生产可用的 TiDB 集群真正跑起来。
一、TiDB 是什么:为什么需要分布式 HTAP 数据库
传统架构里,交易系统跑在 MySQL、PostgreSQL 这类 OLTP 库上,而报表和 BI 又要另建一套 ClickHouse、Hive 等 OLAP 仓库,中间靠 ETL 定时同步。链路一长,数据延迟和一致性就成了噩梦。TiDB 的核心卖点,是在同一集群内同时提供行存(OLTP)与列存(OLAP),用 HTAP(Hybrid Transactional/Analytical Processing)架构让事务与分析互不打架。
它高度兼容 MySQL 协议,老项目几乎可以零改造迁移;底层基于 Raft 做多副本强一致,单节点故障自动切换;存储与计算分离,按需扩节点即可,不必像分库分表那样提前规划「要分几片」。
不过选型要有边界意识:TiDB 不是「把 MySQL 换掉就能更快」的银弹。它的强项在海量数据下的弹性与 HTAP 统一,单机小库的简单读写场景下,TiDB 的多组件开销反而可能不如原生 MySQL 轻快。当你的数据量跨过单机瓶颈、或报表延迟成为业务痛点时,它的价值才真正放大。和 PostgreSQL 高可用 相比,TiDB 的差异化在于原生分布式而非单机多副本,决策时要把「扩展方式」而非「功能列表」放在第一位。
二、核心架构:TiDB / PD / TiKV / TiFlash 四件套
2.1 TiDB Server(无状态 SQL 层)
负责接收 SQL、解析、生成执行计划,本身不存数据。无状态意味着可以横向挂多个实例,前面叠一层 Nginx 反向代理 做负载均衡即可。
2.2 PD(Placement Driver 调度大脑)
集群元信息、时间戳分配(TSO)和 region 调度的总指挥。生产环境 PD 必须部署奇数个(3/5)以保证选主高可用。
2.3 TiKV(行存 + 分布式 KV)
行存引擎,数据按 region 切分,每个 region 三副本通过 Raft 同步。OLTP 的点查、事务都落在这里。
2.4 TiFlash(列存 + HTAP 引擎)
列存副本,通过 Raft Learner 异步同步自 TiKV,专门服务聚合分析类查询,且不挤占 OLTP 资源。
一次查询在四件套之间的流转大致是:TiDB Server 解析 SQL 后向 PD 要路由,定位数据落在哪些 region 与哪些 TiKV 节点;点查直接读 TiKV,聚合类请求则被优化器下推到 TiFlash 列存执行。正因为 TiDB Server 无状态,它的算力可以随并发水平扩展,而存储层又独立于计算层伸缩——这两层解耦是弹性能力的根本来源。
三、单机快速起步:Docker Compose 拉起一套集群
本地验证最简单的方式是用官方 tiup playground,或一份 compose 文件拉起最小集群。下面这份配置适合开发联调,生产请勿把 PD、TiKV 混部在同一块磁盘上。
version: "3"
services:
pd:
image: pingcap/pd:v7.5.0
command: --name=pd1 --client-urls=http://0.0.0.0:2379 --peer-urls=http://0.0.0.0:2380 --initial-cluster=pd1=http://pd:2380
ports: ["2379:2379"]
tikv:
image: pingcap/tikv:v7.5.0
command: --addr=0.0.0.0:20160 --pd=pd:2379 --data-dir=/data
volumes: ["tikv-data:/data"]
depends_on: [pd]
tidb:
image: pingcap/tidb:v7.5.0
command: --path=pd:2379 --store=tikv
ports: ["4000:4000"]
depends_on: [tikv]
tiflash:
image: pingcap/tiflash:v7.5.0
depends_on: [tikv]
volumes:
tikv-data:
启动后用任意 MySQL 客户端连 mysql -h 127.0.0.1 -P 4000 -u root 即可,无需密码。可参考 Docker 编排实战 把这份 compose 接入你的 CI 环境做集成测试。
四、建表与分区:从 MySQL 迁移要注意什么
TiDB 兼容大部分 MySQL DDL,但主键设计有讲究:强烈建议用带业务含义的 AUTO_RANDOM 或显式主键,避免自增主键造成单个 region 写入热点。下面是一张订单表的推荐写法:
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_RANDOM,
user_id BIGINT NOT NULL,
amount DECIMAL(12,2) NOT NULL,
status TINYINT NOT NULL,
created_at DATETIME NOT NULL,
INDEX idx_user (user_id),
INDEX idx_created (created_at)
) PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p202601 VALUES LESS THAN (TO_DAYS('2026-02-01')),
PARTITION p202602 VALUES LESS THAN (TO_DAYS('2026-03-01'))
);
分区表在按时间清理冷数据时只需 DROP PARTITION,比 DELETE 高效且不留碎片。如果你原本的慢查询根因在 PostgreSQL 的执行计划上,思路是相通的——先把 PostgreSQL 慢查询优化 里的索引与统计信息方法论迁移过来,再针对 TiDB 的 region 分布调优。
一个容易被忽视的坑是字符集与排序规则:TiDB 默认 utf8mb4 与 MySQL 一致,但部分老项目用了 utf8 且含 4 字节表情时会在导入阶段报错。迁移前先用 SHOW CREATE TABLE 核对定义,统一成 utf8mb4_0900_ai_ci 或 TiDB 推荐的排序规则,能省下大量排错时间。
五、HTAP 实战:同一份数据跑 OLTP + OLAP
HTAP 的妙处是:写入进 TiKV 行存,分析查询自动走 TiFlash 列存。你可以用 SQL Hint 显式指定走列存,避免大查询拖慢交易:
-- 强制走 TiFlash 列存,做实时报表不挤占 OLTP
SELECT /*+ READ_FROM_STORAGE(TIFLASH[orders]) */
user_id, COUNT(*) AS cnt, SUM(amount) AS gmv
FROM orders
WHERE created_at >= '2026-01-01'
GROUP BY user_id
ORDER BY gmv DESC
LIMIT 100;
| 维度 | TiKV(行存) | TiFlash(列存) |
|---|---|---|
| 适用场景 | 点查、事务、写入 | 聚合、扫描、报表 |
| 一致性 | 强一致(Raft) | 近实时(Learner 异步) |
| 资源隔离 | 与 OLTP 共用 | 独立节点,互不干扰 |
| 典型延迟 | 毫秒级 | 亚秒到秒级 |
这里有个一致性边界要心里有数:TiFlash 通过 Raft Learner 异步追平 TiKV,意味着分析查询读到的是「极短时间前」的快照,而非严格实时。对绝大多数实时大屏、经营报表而言这个延迟可忽略;但若你的业务要求分析与交易在同一事务里强一致(比如「刚下单立刻在报表里看见」且不能差一秒),就不要强行走 TiFlash,而该在应用层做最终一致性的权衡。HTAP 省掉的是 ETL 管道,不是所有一致性语义。
六、性能调优:索引、统计信息与热点治理
TiDB 的优化器依赖统计信息,数据大幅变更后一定要主动收集,否则可能选错执行计划:
-- 收集全表统计信息(生产建议低峰期执行)
ANALYZE TABLE orders;
-- 查看某条慢 SQL 的执行计划
EXPLAIN ANALYZE
SELECT * FROM orders WHERE user_id = 882 AND status = 1;
-- 手动分裂热点 region(写入倾斜时)
SPLIT TABLE orders BETWEEN (0) AND (9223372036854775807) REGIONS 16;
| 现象 | 根因 | 处理手段 |
|---|---|---|
| 写入集中单 region 慢 | 自增主键热点 | 改 AUTO_RANDOM / 打散 |
| 查询计划突变变慢 | 统计信息过期 | ANALYZE TABLE |
| 大查询拖垮交易 | 分析流量挤占 | READ_FROM_STORAGE 走 TiFlash |
| 节点间数据倾斜 | region 分布不均 | PD 调度 / 手动 SPLIT |
七、数据迁移:从 MySQL / PostgreSQL 同步
全量导出用 Dumpling,增量同步靠 TiCDC,能近乎实时地把上游变更投到 TiDB 或下游 Kafka。下面的命令把 MySQL 某库导出为兼容文件:
# 全量导出
tiup dumpling -u root -P 3306 -h 10.0.0.5 \
--database shop -o /data/dump -F 64MiB
# 启动 TiCDC 增量同步到 TiDB
tiup cdc cli changefeed create \
--server=http://cdc:8300 \
--sink-uri="mysql://root@127.0.0.1:4000/" \
--changefeed-id=shop-to-tidb
迁移完成后建议跑一轮回归,对照原库的查询耗时与结果集,必要时可借助 GitHub Actions 流水线 把「迁移校验」固化成定时任务,避免人工遗漏。
八、生产落地检查清单
| 检查项 | 建议 |
|---|---|
| PD / TiKV 副本 | 各组件奇数节点,跨可用区部署 |
| 磁盘 | TiKV 用 NVMe SSD,PD 与 TiKV 分离 |
| 主键设计 | 避免自增热点,优先 AUTO_RANDOM |
| 监控 | 接入 Prometheus + Grafana 看 region / 延迟 |
| 备份 | BR 定期全量 + TiCDC 增量兜底 |
| 连接池 | 前置 proxy 或 Redis 缓存 抗突发读 |
九、迁移前必查:TiDB 与 MySQL 的兼容性边界
兼容性高是 TiDB 的卖点,但并非 100% 等价。生产迁移前,务必对照下表逐项排查,避免上线后才爆出功能不支持:
| 能力 | MySQL | TiDB | 迁移建议 |
|---|---|---|---|
| 外键(Foreign Key) | 支持 | 仅语法兼容,不强制校验 | 业务层兜底或改用应用约束 |
| 自增主键 | 连续 | 可能空洞、单点热点 | 改用 AUTO_RANDOM |
| 存储过程 / 触发器 | 支持 | 有限支持 | 尽量上移到应用层 |
| 隔离级别 | 可 Repeatable Read | 默认 RC,快照隔离 | 复核事务逻辑 |
| JSON / GIS | 成熟 | 基本可用 | 复杂查询先压测 |
把这些边界写进迁移评审文档,配合 GitHub Actions 流水线 做自动化回归,能让「能否迁」从拍脑袋变成可量化结论。多数互联网交易、日志与实时分析场景都能平滑落地;真正卡在存储过程重度依赖或强外键校验的老系统,才需要额外的适配成本。
TiDB 的价值不在「又一个数据库」,而在于把弹性扩展、强一致事务和实时分析收进一套系统。当你被分库分表的运维复杂度压得喘不过气,或报表延迟总追不上业务节奏时,它就是那个值得认真评估的下一张牌。




