目录
0 章节目标
一 TiDB Server架构
二 TiDB Server 作用
三 TiDB Server 的进程
1 SQL语句的解析和编译
2 SQL读写相关模块
3 在线DDL相关模块
4 GC机制与相关模块
四 TiDB Server的缓存
1 TIDB的缓存组成
2 TiDB 缓存管理
3 热点小表缓存
4 热点小表缓存-原理
TiDB Server:SQL 层,对外暴露 MySQL 协议的连接 endpoint,负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。TiDB 层本身是无状态的,实践中可以启动多个 TiDB 实例,通过负载均衡组件(如 LVS、HAProxy 或 F5)对外提供统一的接入地址,客户端的连接可以均匀地分摊在多个 TiDB 实例上以达到负载均衡的效果。TiDB Server 本身并不存储数据,只是解析 SQL,将实际的数据读取请求转发给底层的存储节点 TiKV(或 TiFlash)。
核心线程:
词法分析 lex
语法分析 yacc 生成树形结构
验证:表名列名是否存在等
逻辑优化 :
物理优化 :结合统计信息 选择全表扫描 或 索引扫描 ,如果选择索引 该使用哪个索引等
执行计划相当于导游图
关系型数据库 例如Oracle或者MySQL 是以二维表的形式存储,如何转化为key-value的形式?
编号为主键 想转化为聚簇表
tableID_rowID 构成唯一key
Region是kv的存储单位, 默认是96M 当达到144M的时候会进行split,即region分裂的过程,将一个region分裂成2个region
以region为单位 ,region 里面是kv的键值对 ,可以分布式存储在tikv中
SQL执行计划分为两种 :
复杂查询 例如 范围查询 表连接 嵌套查询 为了避免复杂SQL和tikv耦合太高 ,引入了DistSQL模块,把复杂SQL转换为对单表查询的SQL的组合。
点查 :point 根据主键和唯一索引的等值查询 点查 使用到kv 模块
TIKV client 向tikv集群发送交互请求
Transaction 如果语句中有事务 二阶段提交 锁的管理
PD client transaction通过PDclient与 PD交互 获取TSO
在集群中有多个tidb server .可能有多个DDL 发送到TiDB server上。但是同一时刻只能有一个TiDB server在做DDL
用户发出DDL语句 由模块 start job 模块接受,然后放到job queue队列中。
在同一时刻 只有一个tidb server的角色为owner ,owner角色的 tidb server中从 job queue队列中取DDL,执行完成之后放到history queue中。
owner 角色有任期,并不是固定在一个Tidb Server上。
当成为owner后 ,schema load 会收集所有表的元数据。
队列放到TiKV上主要是为了持久化存储,一旦发生宕机断电可以防止数据丢失。
SQL执行流程中会详细介绍。
这里的GC是指数据库的GC ,并不是后端开发语言golang的GC 。
具体是 MVCC特性中的历史版本数据的回收
数据历史版本的作用:闪回,改错了想改回来可以用到。
历史版本数据可能会很多,对存储空间产生一定压力,所以要定期清理历史版本数据,这个过程就叫做GC。
会有一个 TiDB server 被选举为 GC leader ,TiDB server 会计算出一个时间点 ,比如现在是下午14点钟,计算出一个时间戳 叫做 safe point ,是上午10点钟。这4个小时的历史数据是保留的,但是10点之前的数据不会保留。每10分钟触发一次,找到过期的数据,看上面有没有锁信息,优先处理被drop 的表或索引的历史版本,然后处理delete 等
相关参数 GC_life_time = 10min
Tidb server的缓存实际上使用 全部内存。
1 SQL结果 ,SQL结果不是从TiKV中获取到的吗?但是有一些表连接,子查询等 无法从某一个TikV节点中把所有数据都获取到,可能需要的数据散落在多个TIKV节点,所以我需要一个TiDB server 吧 TiKV的数据汇聚起来,这些操作都是在 TiDB server缓存中完成的。几张大表做join ,对缓存的占用是很大的
另外还有事务修改,如果事务很大 ,改的数据也要放到缓存中
2 线程缓存
3 元数据 统计信息 用户的用户密码
tidb_mem_quota_query :控制每个SQL语句可以使用的缓存量
oom-action :当SQL使用的缓存超过tidb_mem_quota_query参数设置后 ,是中断返回error 还是记录日志。
在后面的故障分析中还会详细讲解
我有一张表很小,不经常修改但 读取特别频繁,这就是热点表。由于这个热点表很小,所以存在一个region上,这个region所在的TiKV负载就会很高。这就是典型的热点问题。
把这个表都读出来 直接缓存到 TiDB的缓存中,这是非常有效的一个解决热点表的方法。
如果这个表需要修改,这个表在内存中也有 在磁盘上也有,需要先修改哪个地方的数据。
热点小表听起来很简单 ,但是要解决缓存与磁盘不一致的问题。
如何把表放到缓存中 使用 alter table table_name cache;
限制:这张表要小于 64M。
放进去后如何保证数据一致 tidb_table_cache_lease = 5 缓存的租约。这个参数模式5秒,这个小表到了缓存中有5秒的租约,在这5秒内可以读 ,但是不能写,阻塞了,要等待租约到期。