TiDB面试题汇总 - 分布式数据库核心考点
📋 基础概念题
1. TiDB的架构组成有哪些?各组件的作用是什么?
难度级别:⭐⭐⭐
考察范围:架构设计/分布式系统
详细解答
TiDB采用计算与存储分离的架构,主要包含以下组件:
核心组件
TiDB Server(计算层)
- 无状态的SQL层
- 负责接收SQL请求
- 执行SQL优化和执行计划生成
- 可水平扩展,提供负载均衡
PD(Placement Driver,调度层)
- 集群的"大脑"
- 存储集群元信息
- 调度和负载均衡
- 分配全局唯一的事务ID
- 生成时间戳(TSO)
TiKV(存储层)
- 分布式KV存储引擎
- 使用RocksDB作为本地存储
- 通过Raft协议保证数据一致性
- 自动进行数据分片(Region)
- 每个Region有多个副本
TiFlash(分析引擎)
- 列式存储引擎
- 实时从TiKV同步数据
- 加速OLAP查询
- 与TiKV互为副本
架构示意
┌─────────────────────────────────────┐
│ 客户端应用 │
└──────────────┬──────────────────────┘
│ MySQL协议
┌──────────────▼──────────────────────┐
│ TiDB Server (无状态SQL层) │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │TiDB-1 │ │TiDB-2 │ │TiDB-N │ │
└──┬───────────────────────────────┬──┘
│ │
│ ┌────────────────────────┐ │
│ │ PD (调度协调) │ │
│ └────────────────────────┘ │
│ │
┌──▼───────────────────────────────▼──┐
│ TiKV (KV存储) │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │Region-1│ │Region-2│ │Region-N│ │
│ │(Raft) │ │(Raft) │ │(Raft) │ │
└──────────────────────────────────────┘
│
┌────────▼──────────┐
│ TiFlash (列存) │
└───────────────────┘2. TiDB如何实现分布式事务?
难度级别:⭐⭐⭐⭐⭐
考察范围:分布式事务/一致性协议
详细解答
TiDB使用基于Percolator的分布式事务模型,结合了2PC(两阶段提交)和MVCC。
Percolator事务流程
go
// 1. Prewrite阶段(第一阶段)
func Prewrite(mutations []Mutation) error {
// 选择一个key作为Primary Key
primaryKey := mutations[0].Key
for _, mut := range mutations {
// 检查写写冲突
if hasConflict(mut.Key, startTS) {
return ErrConflict
}
// 写入Lock和Data
writeLock(mut.Key, primaryKey, startTS)
writeData(mut.Key, mut.Value, startTS)
}
return nil
}
// 2. Commit阶段(第二阶段)
func Commit(mutations []Mutation, commitTS uint64) error {
// 先提交Primary Key
if err := commitPrimary(mutations[0].Key, commitTS); err != nil {
return err
}
// 异步提交Secondary Keys
go func() {
for _, mut := range mutations[1:] {
commitSecondary(mut.Key, commitTS)
}
}()
return nil
}事务模式对比
| 特性 | 乐观事务 | 悲观事务 |
|---|---|---|
| 加锁时机 | Commit时 | 执行DML时 |
| 冲突检测 | 提交时检测 | 实时检测 |
| 适用场景 | 低冲突 | 高冲突 |
| 性能 | 高(无冲突时) | 较低 |
| 兼容性 | 差 | 好(类似MySQL) |
sql
-- 设置事务模式
SET SESSION tidb_txn_mode = 'pessimistic'; -- 悲观事务
SET SESSION tidb_txn_mode = 'optimistic'; -- 乐观事务3. TiDB的数据分片(Region)机制是什么?
难度级别:⭐⭐⭐⭐
考察范围:数据分片/负载均衡
详细解答
TiDB将数据按照Key的Range切分成多个Region。
Region特性
- 默认大小:96MB
- 每个Region有3个副本(可配置)
- 使用Raft协议保证一致性
- 自动split和merge
sql
-- 查看表的Region分布
SHOW TABLE orders REGIONS;
-- 查看Region详情
SELECT
REGION_ID,
START_KEY,
END_KEY,
LEADER_STORE_ID,
PEERS
FROM INFORMATION_SCHEMA.TIKV_REGION_STATUS
WHERE DB_NAME = 'test' AND TABLE_NAME = 'orders';Region分裂示例
初始状态:
┌──────────────────────────────┐
│ Region 1: [0, ∞) │
└──────────────────────────────┘
数据增长后:
┌──────────────┬───────────────┐
│Region 1: │ Region 2: │
│[0, 1000000) │[1000000, ∞) │
└──────────────┴───────────────┘
继续分裂:
┌──────┬──────┬──────┬────────┐
│Reg 1 │Reg 2 │Reg 3 │ Reg 4 │
└──────┴──────┴──────┴────────┘📊 性能优化题
4. 如何解决TiDB的写入热点问题?
难度级别:⭐⭐⭐⭐
考察范围:性能优化/热点问题
详细解答
热点产生原因
- 自增主键: 所有写入都集中在最大的Region
- 时间戳字段: 按时间顺序写入
- 业务特性: 某些热门数据被频繁访问
解决方案
1. 使用SHARD_ROW_ID_BITS
sql
-- 将自增ID打散到多个Region
CREATE TABLE orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2)
) SHARD_ROW_ID_BITS = 4; -- 2^4=16个分片
-- 查看配置
SHOW CREATE TABLE orders;2. 使用AUTO_RANDOM
sql
-- 自动生成随机分布的主键
CREATE TABLE logs (
id BIGINT AUTO_RANDOM PRIMARY KEY,
content TEXT,
created_at TIMESTAMP
);
-- 插入数据(id自动生成)
INSERT INTO logs (content, created_at)
VALUES ('log message', NOW());3. 使用UUID或雪花算法
sql
-- UUID主键
CREATE TABLE events (
id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()),
event_type VARCHAR(50),
created_at TIMESTAMP
);
-- 应用层生成雪花ID
CREATE TABLE messages (
id BIGINT PRIMARY KEY, -- 应用生成
content TEXT
);4. 预分裂Region
sql
-- 创建表时预分裂
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(50)
) PRE_SPLIT_REGIONS = 10;
-- 手动分裂已有表
SPLIT TABLE orders BETWEEN (0) AND (1000000) REGIONS 10;5. TiDB的执行计划如何分析和优化?
难度级别:⭐⭐⭐⭐
考察范围:SQL优化/执行计划
详细解答
分析执行计划
sql
-- 查看执行计划
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
-- 查看实际执行情况
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;
-- 查看详细信息
EXPLAIN FORMAT='verbose' SELECT * FROM orders WHERE user_id = 123;执行计划示例
+---------------------------+---------+-----------+
| id | estRows | task |
+---------------------------+---------+-----------+
| TableReader_7 | 10.00 | root |
| └─Selection_6 | 10.00 | cop[tikv] |
| └─TableFullScan_5 | 10000 | cop[tikv] |
+---------------------------+---------+-----------+
关键指标:
- estRows: 预估行数
- task: 执行位置(root/cop)
- operator: TableReader, IndexReader等优化器Hints
sql
-- 强制使用索引
SELECT /*+ USE_INDEX(orders, idx_user_id) */
* FROM orders WHERE user_id = 123;
-- 强制使用特定Join算法
SELECT /*+ HASH_JOIN(o, u) */
o.*, u.name
FROM orders o
JOIN users u ON o.user_id = u.id;
-- 强制读TiFlash
SELECT /*+ READ_FROM_STORAGE(TIFLASH[orders]) */
DATE(created_at), SUM(amount)
FROM orders
GROUP BY DATE(created_at);
-- 禁用索引
SELECT /*+ IGNORE_INDEX(orders, idx_user_id) */
* FROM orders WHERE user_id = 123;🔧 运维实战题
6. TiDB集群如何扩容和缩容?
难度级别:⭐⭐⭐
考察范围:集群运维/扩缩容
详细解答
使用TiUP扩容
bash
# 1. 编辑扩容配置文件 scale-out.yaml
cat > scale-out.yaml << EOF
tikv_servers:
- host: 10.0.1.14
ssh_port: 22
port: 20160
status_port: 20180
deploy_dir: /tidb-deploy/tikv-20160
data_dir: /tidb-data/tikv-20160
tidb_servers:
- host: 10.0.1.15
ssh_port: 22
port: 4000
status_port: 10080
deploy_dir: /tidb-deploy/tidb-4000
EOF
# 2. 执行扩容
tiup cluster scale-out tidb-cluster scale-out.yaml
# 3. 检查集群状态
tiup cluster display tidb-cluster缩容操作
bash
# 下线TiKV节点(会自动迁移数据)
tiup cluster scale-in tidb-cluster --node 10.0.1.14:20160
# 下线TiDB节点(无状态,可直接下线)
tiup cluster scale-in tidb-cluster --node 10.0.1.15:4000
# 检查下线进度
tiup cluster display tidb-cluster7. 如何监控TiDB集群的健康状态?
难度级别:⭐⭐⭐
考察范围:监控告警/运维
关键监控指标
sql
-- 1. 查看集群拓扑
SELECT * FROM INFORMATION_SCHEMA.CLUSTER_INFO;
-- 2. 查看慢查询
SELECT
query_time,
query,
db,
user
FROM INFORMATION_SCHEMA.SLOW_QUERY
WHERE time >= NOW() - INTERVAL 1 HOUR
ORDER BY query_time DESC
LIMIT 10;
-- 3. 查看热点表
SELECT
TABLE_SCHEMA,
TABLE_NAME,
READ_BYTES,
WRITE_BYTES
FROM INFORMATION_SCHEMA.TABLE_STORAGE_STATS
ORDER BY WRITE_BYTES DESC
LIMIT 10;
-- 4. 查看Region分布
SELECT
STORE_ID,
COUNT(*) as region_count
FROM INFORMATION_SCHEMA.TIKV_REGION_STATUS
GROUP BY STORE_ID;🎯 场景应用题
8. MySQL迁移到TiDB需要注意哪些问题?
难度级别:⭐⭐⭐⭐
考察范围:迁移实践/兼容性
兼容性差异
不支持的特性
sql
-- ❌ 不支持外键
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
FOREIGN KEY (user_id) REFERENCES users(id) -- TiDB不支持
);
-- ✅ 替代方案:应用层保证
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
INDEX idx_user_id (user_id)
);
-- ❌ 不完全支持触发器
CREATE TRIGGER update_time
BEFORE UPDATE ON users
FOR EACH ROW
SET NEW.updated_at = NOW(); -- TiDB不支持
-- ✅ 替代方案:应用层或ON UPDATE CURRENT_TIMESTAMP
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(50),
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);迁移工具和步骤
bash
# 使用TiDB Lightning全量导入
tiup tidb-lightning --config lightning.toml
# 使用DM(Data Migration)实时同步
tiup dm deploy dm-cluster topology.yaml
# 使用Dumpling导出MySQL数据
tiup dumpling -h 127.0.0.1 -P 3306 -u root -o /data/backup9. TiDB如何实现HTAP(混合事务分析处理)?
难度级别:⭐⭐⭐⭐⭐
考察范围:HTAP架构/TiFlash
详细解答
sql
-- 1. 为表添加TiFlash副本
ALTER TABLE orders SET TIFLASH REPLICA 1;
-- 2. 检查副本状态
SELECT * FROM INFORMATION_SCHEMA.TIFLASH_REPLICA
WHERE TABLE_NAME = 'orders';
-- 3. OLTP查询(自动走TiKV)
SELECT * FROM orders WHERE id = 12345;
-- 4. OLAP查询(自动走TiFlash)
SELECT
DATE(created_at) as day,
COUNT(*) as order_count,
SUM(amount) as total_amount
FROM orders
WHERE created_at >= '2024-01-01'
GROUP BY DATE(created_at);
-- 5. 强制使用TiFlash
SELECT /*+ READ_FROM_STORAGE(TIFLASH[orders]) */
user_id,
COUNT(*) as order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 100;HTAP架构优势
- ✅ 同一份数据服务OLTP和OLAP
- ✅ 实时数据分析,无需ETL
- ✅ 降低数据一致性问题
- ✅ 简化架构,降低成本
🔍 面试准备建议
- 架构理解: 深入理解TiDB的分层架构和各组件职责
- 分布式原理: Raft、2PC、Percolator等核心算法
- 性能优化: 热点问题、索引优化、执行计划分析
- 运维经验: 扩缩容、备份恢复、监控告警
- 迁移实践: MySQL迁移经验和兼容性处理
- 对比分析: 与MySQL、MongoDB等数据库的对比
