Skip to content

TiDB - 分布式NewSQL数据库

TiDB是一个开源的分布式NewSQL数据库,支持水平扩展、强一致性事务和MySQL协议兼容。

tidb 的主键 id 不建议自增

tidb 是一款分布式数据库,作为 mysql 分库分表场景下的替代产品,可以更好的对数据进行分片。

它通过引入Range的概念进行数据表分片,比如第一个分片表的 id 在 0~2kw,第二个分片表的 id 在 2kw~4kw。这其实就是根据 id 范围进行数据库分表

它的语法几乎跟 mysql 一致,用起来大部分时候是无感的。

但跟 mysql 有一点很不一样的就是,mysql 建议 id 自增,但tidb 却建议使用随机的 uuid。原因是如果 id 自增的话,根据范围分片的规则,一段时间内生成的 id 几乎都会落到同一个分片上,比如下图,从3kw开始的自增 uuid,几乎都落到range 1这个分片中,而其他表却几乎不会有写入,性能没有被利用起来。出现一表有难,多表围观的场面,这种情况又叫写热点问题。

写热点问题

所以为了充分的利用多个分表的写入能力,tidb 建议我们写入时使用随机 id,这样数据就能被均匀分散到多个分片中。

📋 核心概念

TiDB架构

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

  • TiDB Server: 无状态的SQL层,负责处理SQL请求
  • PD (Placement Driver): 集群元信息管理和调度
  • TiKV: 分布式KV存储引擎,存储实际数据
  • TiFlash: 列式存储引擎,用于OLAP查询

🎯 核心特性

1. 水平扩展能力

sql
-- TiDB支持在线水平扩展
-- 添加TiKV节点自动实现容量扩展
-- 添加TiDB Server节点提升查询并发能力

-- 查看集群拓扑
SHOW STATS_META;

-- 查看Region分布
SHOW TABLE t1 REGIONS;

2. 强一致性事务

sql
-- TiDB支持ACID事务,默认隔离级别为可重复读
START TRANSACTION;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

COMMIT;

-- 支持乐观事务和悲观事务
SET SESSION tidb_txn_mode = 'pessimistic';

3. MySQL兼容性

sql
-- TiDB兼容MySQL 5.7协议和语法
-- 可以使用MySQL客户端直接连接

-- 支持大部分MySQL语法
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_username (username)
) ENGINE=InnoDB;

-- 支持MySQL函数
SELECT COUNT(*), DATE_FORMAT(created_at, '%Y-%m') as month
FROM users
GROUP BY month;

📊 TiDB vs 传统数据库对比

TiDB vs MySQL

特性TiDBMySQL
扩展性水平扩展,理论无上限垂直扩展,受单机限制
高可用自动故障转移,Multi-Raft需要额外HA方案(MHA、MGR等)
事务分布式事务,强一致性单机事务
容量PB级TB级(分库分表)
SQL兼容兼容MySQL 5.7完全兼容
OLAP性能TiFlash列存支持需要额外OLAP引擎
分片自动分片,透明需要手动分库分表
运维复杂度分布式系统,较复杂单机简单,分片复杂

TiDB vs PostgreSQL

特性TiDBPostgreSQL
扩展性原生分布式Citus扩展或分片
JSON支持基础支持强大的JSONB
GIS支持基础支持PostGIS功能完善
窗口函数支持完全支持
全文搜索基础支持内置全文搜索
生态发展中成熟丰富

TiDB vs MongoDB

特性TiDBMongoDB
数据模型关系型(表)文档型(JSON)
查询语言SQLMongoDB Query Language
事务ACID,分布式事务ACID,多文档事务
Schema强Schema灵活Schema
Join性能原生支持受限,性能较差
写入性能中等
适用场景结构化数据,复杂查询半结构化数据,灵活存储

💡 最佳实践

1. 表设计建议

sql
-- 主键设计:避免使用AUTO_INCREMENT导致热点
-- 推荐使用SHARD_ROW_ID_BITS分散热点
CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    amount DECIMAL(10,2),
    created_at TIMESTAMP
) SHARD_ROW_ID_BITS = 4;

-- 或使用UUID/雪花算法生成分散的主键
CREATE TABLE logs (
    id VARCHAR(36) PRIMARY KEY,  -- UUID
    content TEXT,
    created_at TIMESTAMP
);

2. 索引优化

sql
-- 合理使用索引
CREATE INDEX idx_user_created ON orders(user_id, created_at);

-- 查看索引使用情况
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

-- 强制使用索引
SELECT /*+ USE_INDEX(orders, idx_user_created) */ 
    * FROM orders WHERE user_id = 123;

3. 分区表使用

sql
-- Range分区
CREATE TABLE sales (
    id BIGINT,
    amount DECIMAL(10,2),
    sale_date DATE
) PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
);

-- Hash分区
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    name VARCHAR(50)
) PARTITION BY HASH(id) PARTITIONS 10;

4. 混合负载处理

sql
-- OLTP查询走TiKV(行存)
SELECT * FROM orders WHERE id = 12345;

-- OLAP查询走TiFlash(列存)
SELECT /*+ READ_FROM_STORAGE(TIFLASH[orders]) */
    DATE(created_at), SUM(amount)
FROM orders
WHERE created_at >= '2024-01-01'
GROUP BY DATE(created_at);

🔧 性能调优

查询优化

sql
-- 查看执行计划
EXPLAIN SELECT * FROM orders WHERE user_id = 123;

-- 分析执行时间
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

-- 查看慢查询
SELECT * FROM INFORMATION_SCHEMA.SLOW_QUERY 
WHERE time > '2024-01-01' 
ORDER BY query_time DESC 
LIMIT 10;

配置优化

sql
-- 调整并发参数
SET GLOBAL tidb_executor_concurrency = 8;

-- 调整内存限制
SET SESSION tidb_mem_quota_query = 8 << 30;  -- 8GB

-- 优化器Hints
SELECT /*+ HASH_JOIN(t1, t2) */ 
    t1.*, t2.* 
FROM t1 JOIN t2 ON t1.id = t2.user_id;

📈 适用场景

适合使用TiDB的场景

  1. 数据量大且持续增长: TB到PB级数据
  2. 需要水平扩展: 业务快速增长,数据量不可预测
  3. 强一致性要求: 金融、电商等对数据一致性要求高
  4. 复杂SQL查询: 需要Join、聚合等复杂分析
  5. HTAP混合负载: 同时需要OLTP和OLAP
  6. MySQL迁移: 现有MySQL应用需要扩展

不适合的场景

  1. 小数据量: 百万级以下数据,单机MySQL足够
  2. 极致读写性能: 纯KV场景,Redis等更合适
  3. 频繁DDL: TiDB的DDL相对较慢
  4. 复杂存储过程: 兼容性有限

🚀 快速开始

使用TiUP部署

bash
# 安装TiUP
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh

# 启动测试集群
tiup playground

# 连接到TiDB
mysql -h 127.0.0.1 -P 4000 -u root

Docker部署

bash
# 使用Docker Compose
git clone https://github.com/pingcap/tidb-docker-compose.git
cd tidb-docker-compose
docker-compose up -d

# 连接
mysql -h 127.0.0.1 -P 4000 -u root

📚 学习资源

🎯 面试重点

  1. 架构理解: TiDB的三层架构及各组件职责
  2. 分布式事务: Percolator事务模型
  3. Raft协议: Multi-Raft实现原理
  4. 性能优化: 热点问题、索引优化、SQL调优
  5. 与MySQL差异: 兼容性、功能差异
  6. HTAP能力: TiFlash的作用和使用场景

正在精进