一、TiDB 架构全景:为什么选择NewSQL
在传统数据库领域,我们长期面临一个经典的权衡困境:关系型数据库(如 MySQL、PostgreSQL)提供了强一致性和丰富的 SQL 支持,但水平扩展能力有限;NoSQL 数据库(如 Cassandra、MongoDB)擅长横向扩展,却牺牲了事务和 SQL 的便利性。TiDB 作为新一代 NewSQL 数据库,通过原生分布式架构同时实现了 OLTP 事务处理和 OLAP 分析查询——即 HTAP(Hybrid Transactional and Analytical Processing)能力。
TiDB 的核心设计理念是「兼容 MySQL 协议 + 水平扩展 + 强一致性事务」。这意味着现有的 MySQL 应用可以几乎零改造地迁移到 TiDB,同时获得从单机到数百节点的弹性扩展能力。在国内,TiDB 已被知乎、哔哩哔哩、小米、美团等大规模生产环境验证,社区活跃度和技术成熟度均处于领先地位。
TiDB 的整体架构由三个核心组件构成:
- TiDB Server:无状态的 SQL 解析与优化层,负责接收客户端请求、生成执行计划、协调分布式计算
- TiKV:基于 Raft 共识算法的分布式 Key-Value 存储引擎,承载所有数据并保证强一致性
- PD(Placement Driver):集群元数据管理与调度中心,负责 Region 分配、负载均衡和时间戳分配

二、TiKV 存储引擎深度解析
2.1 从 Key-Value 到关系模型:数据映射原理
TiKV 底层使用 Rust 编写,基于 RocksDB 作为本地存储引擎,通过 Raft 协议实现多副本一致性。理解 TiDB 的关键在于弄清它如何将关系表映射到 Key-Value 存储:
每张表的每一行数据被编码为一个 Key-Value 对。对于聚簇表(Clustered Index,TiDB 默认),主键直接构成 Key 的一部分:
1
2
3
4
5
6
7
8 # 聚簇表 Key 编码规则
Key: tablePrefix_tableID_recordPrefix_主键编码
Value: 其余列数据的编码
# 示例:users 表 (tableID=61, 主键=id)
# 行 id=1, name='Alice', age=30
Key: t61_r1
Value: (encoded: name='Alice', age=30)
对于二级索引,TiDB 将索引数据也存储为独立的 Key-Value 对:
1
2
3
4
5
6
7 # 二级索引 Key 编码规则
Key: tablePrefix_tableID_indexPrefix_indexID_索引列值_主键
Value: nil(唯一索引)或 主键(非唯一索引)
# 示例:users 表的 name 索引 (indexID=1)
Key: t61_i1_Alice_1
Value: nil
这种编码方式让索引扫描可以通过 Key 的前缀范围扫描高效完成,而无需回表查询。
2.2 Region:数据分片与调度的基本单位
TiKV 将 Key 空间按范围划分为 Region(默认 96MB),每个 Region 由多个副本(默认 3 副本)通过 Raft Group 管理。Region 是数据调度的最小单位——PD 可以将热点 Region 分裂或迁移到其他节点,实现负载均衡。
1
2
3
4
5
6
7
8
9 # Region 分裂过程示例
# 原 Region: [a, z) 在 Node1 上成为热点
# PD 触发分裂 →
# Region A: [a, m) → 仍留在 Node1
# Region B: [m, z) → 迁移到 Node3
# 查看集群 Region 分布
tiup ctl pd -u http://127.0.0.1:2379 region \
--key="" --limit=100
Region 的自动分裂与合并是 TiDB 弹性扩展的核心机制。当 Region 数据量超过阈值(默认 144MB)时自动分裂;当相邻小 Region 数据量之和低于阈值时自动合并,减少 Raft Group 开销。
2.3 Raft 共识:强一致性的保障
每个 Region 的多个副本组成一个 Raft Group,所有写操作必须通过 Leader 副本进行,Follower 副本通过 Raft 日志同步数据。这套机制保证了:
- 线性一致性:任何已提交的写操作不会丢失(即使多数副本存活)
- Leader 选举:Leader 故障后自动在剩余副本中选出新 Leader(选举超时默认 3 秒)
- 读一致性:通过 ReadIndex 机制,Follower 也能提供强一致性读,避免所有读流量压在 Leader 上
1
2
3
4
5
6
7
8
9
10 # Raft 关键参数调优(tikv.toml)
[raftstore]
# Region 大小阈值,超过触发分裂
region-max-size = "144MB"
# Region 分裂检查间隔
split-region-check-interval = "10s"
# Raft 心跳间隔
raft-heartbeat-ticks = 2
# 选举超时(心跳tick数)
raft-election-timeout-ticks = 10

三、分布式事务:从 2PC 到乐观/悲观模型
3.1 Percolator 模型:TiDB 的事务引擎
TiDB 的事务模型灵感来自 Google Percolator 论文,通过两阶段提交(2PC)在分布式 Key-Value 存储上实现 ACID 事务。核心概念:
- 时间戳分配:PD 作为全局时钟源(TSO),为每个事务分配单调递增的时间戳
- 乐观事务:先缓存所有修改,提交时再检测冲突(适合低冲突场景)
- 悲观事务:写入前先加锁,避免提交时冲突回滚(TiDB v4.0+ 默认)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 -- 悲观事务示例(TiDB 默认行为)
BEGIN PESSIMISTIC;
-- 对目标行加锁(等效 SELECT ... FOR UPDATE)
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
-- 执行转账
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
-- 对比乐观事务
BEGIN OPTIMISTIC;
-- 不加锁,直接执行
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- 提交时检测冲突,冲突则回滚重试
COMMIT;
3.2 事务隔离级别与 MVCC
TiDB 通过 MVCC(多版本并发控制)实现快照隔离(Snapshot Isolation),在 Key-Value 层面,每个 Key 的多个版本通过时间戳区分:
1
2
3
4
5
6
7 # MVCC 存储结构(简化)
Key: t61_r1 TS: 100 Value: (Alice, 30) # 版本1
Key: t61_r1 TS: 200 Value: (Alice, 31) # 版本2(age更新)
Key: t61_r1 TS: 300 Value: (Alice, 31, NYC) # 版本3(city更新)
# 事务 TS=250 的读操作会看到版本2
# 事务 TS=350 的读操作会看到版本3
TiDB 的隔离级别行为与 MySQL 对比:
| 隔离级别 | MySQL InnoDB | TiDB |
|---|---|---|
| READ UNCOMMITTED | 可读到未提交数据 | 等价于 READ COMMITTED |
| READ COMMITTED | 语句级快照 | 语句级快照 |
| REPEATABLE READ | 事务级快照(默认) | 事务级快照(默认) |
| SERIALIZABLE | 加锁实现 | 等价于 REPEATABLE READ |
需要特别注意的是,TiDB 的 REPEATABLE READ 不会出现幻读,但 SERIALIZABLE 级别实际等效于 REPEATABLE READ——这在使用 ORM 或依赖严格序列化的应用中需留意。
四、TiFlash 与 HTAP:实时分析能力
4.1 TiFlash 列式存储引擎
HTAP 的核心是 TiFlash——一个基于 ClickHouse 的列式存储引擎,通过 Raft Learner 角色异步复制 TiKV 数据。TiFlash 的关键优势:
- 列式存储:分析查询只需读取涉及的列,IO 效率远高于行存
- 向量化执行:利用 SIMD 指令批量处理数据
- 数据一致性:通过 Raft 同步保证,可设置强一致性读或最终一致性读
- 资源隔离:TiFlash 节点独立部署,不影响 TiKV 的 OLTP 性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 -- 强制使用 TiFlash 副本进行分析查询
SET SESSION tidb_isolation_read_engines = 'tiflash';
SELECT
region,
product_category,
COUNT(*) AS order_count,
SUM(amount) AS total_revenue,
AVG(amount) AS avg_order
FROM orders
WHERE order_date >= '2026-01-01'
GROUP BY region, product_category
ORDER BY total_revenue DESC
LIMIT 20;
-- 查看查询使用了哪个引擎
EXPLAIN ANALYZE SELECT COUNT(*) FROM orders;
-- 观察 execution info 中的 "tiflash" 或 "tikv" 标识
4.2 智能路由:MPP 与代价优化
TiDB 优化器会根据查询特征自动选择执行引擎:
- 点查、小范围扫描 → 路由到 TiKV(行存更高效)
- 大范围聚合分析 → 路由到 TiFlash(列存 + MPP 并行)
- 混合查询 → 优化器根据代价估算自动选择
1
2
3
4
5
6
7
8
9
10 # 控制引擎选择的 hints
/*+ read_from_storage(tikv[orders]) */ -- 强制走 TiKV
/*+ read_from_storage(tiflash[orders]) */ -- 强制走 TiFlash
# 配置 TiFlash 副本同步策略
ALTER TABLE orders SET TIFLASH REPLICA 2 LOCATION_LABELS 'dc:east';
# 查看副本同步进度
SELECT * FROM information_schema.tiflash_replica
WHERE table_name = 'orders';

五、SQL 兼容性与迁移实战
5.1 MySQL 兼容性清单
TiDB 高度兼容 MySQL 5.7 协议和语法,但不支持的功能需提前确认:
| 功能 | 兼容性 | 替代方案 |
|---|---|---|
| 存储过程 | 部分支持(v7.5+) | 业务逻辑上移到应用层 |
| 触发器 | 不支持 | 使用应用层事件或 CDC |
| 外键约束 | v6.6+ 支持 | 早期版本需应用层保证 |
| XA 事务 | 不支持 | 使用 TiDB 原生分布式事务 |
| 自增 ID | 支持(但非连续) | AUTO_ID_CACHE 控制缓存大小 |
| 视图 | 支持 | — |
| 窗口函数 | 支持 | — |
5.2 从 MySQL 迁移的完整流程
TiDB 提供了 DM(Data Migration)工具实现 MySQL → TiDB 的全量 + 增量迁移:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 # DM 迁移任务配置示例 (dm-task.yaml)
task-name: "mysql-to-tidb"
task-mode: "all" # 全量 + 增量
target-database:
host: "tidb-server"
port: 4000
user: "root"
password: ""
mysql-instances:
- source-id: "mysql-replica-01"
block-allow-list: "instance"
mydumper-config-name: "global"
loader-config-name: "global"
syncer-config-name: "global"
block-allow-list:
instance:
do-dbs: ["app_db", "user_db"]
ignore-dbs: ["test", "tmp"]
mydumpers:
global:
threads: 4
chunk-filesize: "64MB"
loaders:
global:
pool-size: 16
syncers:
global:
worker-count: 16
batch: 100
1
2
3
4
5
6
7
8
9
10
11
12 # 启动 DM 迁移
# 1. 部署 DM 集群
tiup deploy dm-cluster 2.0.9 ./dm-topology.yaml user
# 2. 创建数据源
dmctl operate-source create ./source1.yaml
# 3. 启动迁移任务
dmctl start-task ./dm-task.yaml
# 4. 监控迁移状态
dmctl query-status mysql-to-tidb
5.3 数据校验与切流
迁移完成后,使用 sync-diff-inspector 进行数据一致性校验:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 # sync-diff-inspector 配置
data-sources:
source:
host: mysql-server
port: 3306
user: root
password: ""
target:
host: tidb-server
port: 4000
user: root
password: ""
check-tables:
- schema: app_db
tables:
- users
- orders
- products
# 运行校验
./sync_diff_inspector --config=./config.toml
# 输出示例
# Summary:
# Total tables: 15
# Matched: 15
# Failed: 0
# Skipped: 0
六、集群部署与运维实战
6.1 TiUP 部署:从零搭建生产集群
TiUP 是 TiDB 官方的部署管理工具,支持一键部署、扩缩容和版本升级:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 # 编写拓扑文件 topology.yaml
global:
user: tidb
deploy_dir: /tidb-deploy
data_dir: /tidb-data
pd_servers:
- host: 10.0.1.1
- host: 10.0.1.2
- host: 10.0.1.3
tikv_servers:
- host: 10.0.2.1
config:
server.labels: { zone: "east", rack: "r1" }
- host: 10.0.2.2
config:
server.labels: { zone: "east", rack: "r2" }
- host: 10.0.2.3
config:
server.labels: { zone: "west", rack: "r1" }
tidb_servers:
- host: 10.0.3.1
- host: 10.0.3.2
tiflash_servers:
- host: 10.0.4.1
config:
storage.main.dir: /data1/tiflash
monitoring_servers:
- host: 10.0.5.1
grafana_servers:
- host: 10.0.5.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14 # 部署集群
tiup cluster deploy prod-cluster v8.5.0 topology.yaml
# 启动集群
tiup cluster start prod-cluster
# 查看集群状态
tiup cluster display prod-cluster
# 在线扩容 TiKV 节点
tiup cluster scale-out prod-cluster scale-out.yaml
# 滚动升级
tiup cluster upgrade prod-cluster v8.5.1 --transfer-timeout 300
6.2 关键监控指标与告警
TiDB 内置 Grafana 仪表盘,以下是最需关注的核心指标:
| 组件 | 指标 | 告警阈值 | 含义 |
|---|---|---|---|
| PD | pd_scheduler_store_status | 差值 > 20% | Store 数据量不均衡 |
| PD | pd_region_health_status | miss_region > 0 | 存在缺失副本 |
| TiKV | raft_apply_log_duration | P99 > 100ms | Raft 应用延迟高 |
| TiKV | coprocessor_request_duration | P99 > 1s | 协处理器慢查询 |
| TiDB | tidb_server_query_duration | P99 > 1s | SQL 执行延迟 |
| TiKV | storage_engine_rate | 接近磁盘上限 | IO 成为瓶颈 |
6.3 备份恢复:BR 与快照
TiDB 提供两种备份方案:BR(Backup & Restore)用于大数据量快速备份,逻辑导出(Dumpling)用于小数据量或跨系统迁移:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 # BR 全量备份到 S3
br backup full \
--pd 10.0.1.1:2379 \
--storage s3://backup-bucket/tidb/2026-08-16 \
--s3.endpoint s3.amazonaws.com \
--concurrency 16 \
--checksum true
# BR 增量备份(基于上一次备份时间戳)
br backup full \
--pd 10.0.1.1:2379 \
--storage s3://backup-bucket/tidb/incr-2026-08-16 \
--lastbackupts 448853546496000000
# BR 恢复
br restore full \
--pd 10.0.1.1:2379 \
--storage s3://backup-bucket/tidb/2026-08-16 \
--concurrency 32
# EBS 快照备份(云原生方案,秒级 RPO)
br backup ebs \
--pd 10.0.1.1:2379 \
--storage s3://backup-bucket/ebs-snapshots
七、性能调优:从 SQL 到集群参数
7.1 SQL 层面优化
TiDB 的优化器基于代价估算(CBO),但某些场景需要手动干预:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 -- 1. 统计信息收集(影响执行计划质量)
ANALYZE TABLE orders FULL;
-- 设置自动收集策略
SET GLOBAL tidb_auto_analyze_ratio = 0.5;
SET GLOBAL tidb_auto_analyze_start_time = '00:00 +0000';
SET GLOBAL tidb_auto_analyze_end_time = '06:00 +0000';
-- 2. 索引优化
-- TiDB 支持 Hash Index(等值查询优化)
ALTER TABLE sessions ADD INDEX idx_token (token) USING HASH;
-- 复合索引遵循最左前缀原则(与 MySQL 一致)
ALTER TABLE orders ADD INDEX idx_user_date (user_id, created_at);
-- 3. 使用 SQL Hints 控制执行计划
-- 强制使用索引
SELECT /*+ USE_INDEX(orders, idx_user_date) */
* FROM orders WHERE user_id = 100;
-- 并行执行(v7.0+)
SET SESSION tidb_executor_concurrency = 16;
-- 4. 绑定执行计划(执行计划稳定性)
CREATE GLOBAL BINDING FOR
SELECT * FROM orders WHERE user_id = 100
USING
SELECT /*+ USE_INDEX(orders, idx_user_date) */
* FROM orders WHERE user_id = 100;
7.2 TiKV 调优参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 # tikv.toml 关键参数
[storage]
# 预写日志目录(建议独立 SSD)
wal-dir = "/data/wal"
# Raft 引擎配置
[raftdb]
max-sub-compactions = 2
[rocksdb]
max-sub-compactions = 3
# 列族写入缓冲区
[rocksdb.defaultcf]
write-buffer-size = "128MB"
max-write-buffer-number = 5
# 读取线程池
[readpool.coprocessor]
high-concurrency = 8
normal-concurrency = 8
low-concurrency = 8
# GC 生命周期(影响历史版本数量)
[gc]
enable = true
batch-size = 512
7.3 热点问题诊断与解决
写入热点是 TiDB 运维中最常见的问题之一。典型场景:自增主键导致所有写入集中在最后一个 Region。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 # 诊断热点
# 通过 PD 监控面板查看 Region 写入分布
# 或通过 SQL 查看
SELECT
TABLE_ID,
INDEX_NAME,
DB_NAME,
TABLE_NAME,
REGION_ID,
REGION_WRITTEN_BYTES
FROM information_schema.tikv_region_status
WHERE REGION_WRITTEN_BYTES > 10485760 -- 10MB
ORDER BY REGION_WRITTEN_BYTES DESC
LIMIT 20;
# 解决方案1:使用 SHARD_ROW_ID_BITS 打散热点
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT,
user_id BIGINT,
amount DECIMAL(10,2),
PRIMARY KEY (id)
) SHARD_ROW_ID_BITS = 4 PRE_SPLIT_REGIONS = 4;
# 解决方案2:使用非自增主键(如 UUID 或雪花算法)
CREATE TABLE orders (
id CHAR(36) PRIMARY KEY, -- UUID
...
);
# 解决方案3:预切分 Region(适合批量导入)
ALTER TABLE orders PRE_SPLIT_REGIONS = 8;
八、总结与选型建议
TiDB 作为分布式 NewSQL 数据库的代表,在以下场景表现出色:
- MySQL 兼容 + 水平扩展需求:现有 MySQL 应用增长到单机瓶颈,需要透明水平扩展
- HTAP 需求:同一套数据既要支撑高并发事务,又要支撑实时分析
- 高可用要求:不能接受数据丢失和长时间停机(TiDB RPO=0,RTO<30s)
- 多数据中心容灾:通过 PD 调度和 Region 迁移实现跨机房容灾
但也需要注意 TiDB 的局限性:
- 小数据量场景(< 500GB)MySQL 单机更简单高效
- 超高频点查场景(> 50万 QPS 单行点查),Redis + MySQL 组合可能更优
- 复杂存储过程密集型应用迁移成本较高
- 运维复杂度高于单机数据库,需要一定的分布式系统经验
TiDB 的版本迭代速度很快,当前 v8.x 版本已支持资源管控(Resource Control)、Flashback Cluster、PITR(Point-in-Time Recovery)等企业级特性。对于正在面临数据库扩展瓶颈的团队,TiDB 值得作为 MySQL 扩展方案的首选评估对象。从 POC 到生产落地的路径已经非常成熟——TiUP 部署、DM 迁移、BR 备份三件套足以覆盖绝大多数场景。
汤不热吧