Skip to content

TiDB面试题汇总 - 分布式数据库核心考点

📋 基础概念题

1. TiDB的架构组成有哪些?各组件的作用是什么?

难度级别:⭐⭐⭐
考察范围:架构设计/分布式系统

详细解答

TiDB采用计算与存储分离的架构,主要包含以下组件:

核心组件

  1. TiDB Server(计算层)

    • 无状态的SQL层
    • 负责接收SQL请求
    • 执行SQL优化和执行计划生成
    • 可水平扩展,提供负载均衡
  2. PD(Placement Driver,调度层)

    • 集群的"大脑"
    • 存储集群元信息
    • 调度和负载均衡
    • 分配全局唯一的事务ID
    • 生成时间戳(TSO)
  3. TiKV(存储层)

    • 分布式KV存储引擎
    • 使用RocksDB作为本地存储
    • 通过Raft协议保证数据一致性
    • 自动进行数据分片(Region)
    • 每个Region有多个副本
  4. 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的写入热点问题?

难度级别:⭐⭐⭐⭐
考察范围:性能优化/热点问题

详细解答

热点产生原因

  1. 自增主键: 所有写入都集中在最大的Region
  2. 时间戳字段: 按时间顺序写入
  3. 业务特性: 某些热门数据被频繁访问

解决方案

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-cluster

7. 如何监控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/backup

9. 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
  • ✅ 降低数据一致性问题
  • ✅ 简化架构,降低成本

🔍 面试准备建议

  1. 架构理解: 深入理解TiDB的分层架构和各组件职责
  2. 分布式原理: Raft、2PC、Percolator等核心算法
  3. 性能优化: 热点问题、索引优化、执行计划分析
  4. 运维经验: 扩缩容、备份恢复、监控告警
  5. 迁移实践: MySQL迁移经验和兼容性处理
  6. 对比分析: 与MySQL、MongoDB等数据库的对比

正在精进