《一条 select 语句在 TiDB Server 层都发生了什么》
作者: Ming 原文来源:https://tidb.net/blog/08abac12
前言
相信我们平时接触数据库,对于 select 语句那是在熟悉不过了。就比如像下面的这条语句:
这条语句就是一条普通的查询语句,那当我们放到数据库执行的时候,它又经历了怎样的过程的,接下来就让我们看一下,一条 select 语句在 TiDB Server 层都发生了什么。
简介
TiDB 数据库由 PD + TiDB Server + TiKV 组成。
PD 主要负责:集群整体拓扑结构的存储 / 分配全局 ID 和事务 ID/ 生成全局 TSO 时间戳 / 收集集群信息进行调度 / 提供 TiDB Dashboard 服务
TiDB Server 主要负责:客户端的连接(MySQL 协议)/SQL 语句析、编译 / 数据转化 /SQL 语执行 / 在线 DDL 语句 /GC
TiKV 主要负责:数据持久化 / 分布式事务支持 / 副本的强一致性和高可用性 /MVCC/Coprocessor(协同处理器)
| 以上则是各个组件主要负责的功能。 | |
这次主要介绍的是 Select 语句在 TiDB Server 层都由哪些操作,接下来先让我们看一下 TiDB Server 的架构:
可以看到,我们的 TiDB Server 主要由各个模块组成,每一块的功能各不相同,结合图片与介绍,我们可以大致的对 TiDB 各个模块的功能有一个认知,接下来就根据 select 语句的执行流程,来看一看每一个模块的作用。
流程解析
1、*Protocol Layer 模块*
如果我们在 Linux 操作系统上连接 TiDB 服务,因为是兼容 mysql 的,所以我们只需要执行 mysql 的连接命令,即可连接进入数据库当中,这样我们才可以执行 sql 语句,普遍方式如下:
连接的时候,我们会需要经过 TCP 的三次握手,如果我们的服务并没有启动的话,则会收到如下报错:
当我们建立完 TCP 的连接后,我们的数据库就会先对你的用户与密码进行判断,如果用户和密码不对。就会收到 ”Access denied for user” 的报错,然后结束执行。
如果我们的账号密码没有问题,那我们就成功的进入到了数据库内,在数据库内我们的操作,基于之前获取的用户权限来进行,如果在此时管理员修改了该用户的权限,因为我们已经记录了所需权限,所以不会有问题,而是在我们重新建立连接后,权限才会进行刷新。
建立连接后,如果我们想要知道我们的数据库有多少个连接,由于 TiDB 是分布式数据库,所以我们可以通过自带的 INFORMATION_SCHEMA 下面的 cluster_processlist 查看到连接信息。
2、Parse 模块
在正式执行 SQL 查询语句之前,TiDB 会先对 SQL 语句进行解析编译,Parse 主要负责解析我们的 SQL 语句,当我们连接数据库后执行一条 select 语句,该模块会首先接收到,并将其进行一个词法分析(lex)+ 语法分析(yacc),它们的操作会将我们的查询语句进行分析,判断是否符合 TiDB 的语法,如果我们输入的语句通过判断,判断出并不符合 TiDB 的语法则会报错,如下图一样:
并且经过的时候会生成一个 AST 抽象语法数,类似如下这张图:
这里值得注意的是,语法分析只是判断是否符合 TiDB 的语法,并不会针对于表是否存在,库是否存在这些进行判断。这些判断是由 compile 模块来进行的。
3、*Compile 模块*
我们的查询语句通过 Parse 模块产生 AST 抽象语法树以后呢,就会到达 Compile 模块,首先呢,该模块会对查询语句进行合法性验证,判断是否上述说的一些类似于库 / 表是否存在等,如下:
在合法性验证结束后,会对语句进行逻辑优化 + 物理优化,逻辑优化的意思呢,就是说,会根据 SQL 层面的操作进行相关的优化,物理优化呢就是针对于数据的分布 / 数据大小来决定我们的执行方式,当我们的查询语句经历的逻辑 + 物理优化后,就会生产执行计划,我们也可以通过 explain sql 语句进行查看,来判断是否走到了预期的效果,如下:
4、*Executor 模块*
通过 Compile 模块后就会来到 Executor 模块,该模块会对我们的 SQL 语句进行判断,这个判断的意思呢,就是说它会将我们的语句进行分辨,分辨是点查还是复杂 SQL,这时候就会产生两种情况。
当 Executor 模块判断执行 SQL 是点查时,则会交给 KV 模块来进行,KV 模块会通过 TiKV Client 模块来跟 TiKV 建立连接从 RocksDB-KV 当中获取数据
当 Executor 模块判断执行 SQL 是复杂 SQL 时,则会交给 DistSQL 模块,DistSQL 模块会将复杂 SQL 进行拆分,分解成多个单表查询操作,然后在通过 TiKV Client 模块跟 TiKV 建立连接从 RocksDB-KV 当中获取数据。
值得注意的是,TiDB 的数据是转换为 Key-Value 形式来进行存储的,并且是在 TiDB Server 层来进行的。Executor 当中就会有一个将关系型数据转换为 Key-Value 的过程。
5、获取 TSO
在我们执行语句的过程中 TiDB Server 会先去 PD 获取 start.ts 与 commit.ts ,这里呢会将获取分为 6 步来完成,如下:
6、获取 Region 位置信息
TiDB 是一个分布式的数据库,PD 充当了一个类似于大脑的角色,我们的查询语句,需要知道数据存放在哪,就需要通过 PD 来获得路由信息,然后才将请求发送给 TiKV。为了防止过于频繁的请求 PD 造成性能问题,TiDB Server 呢会通过缓存机制来解决此类问题,获取 Region 位置信息的流程如下:
7、返回数据
当我们从 TiKV 当中获取到所要查询数据后,会通过 Executor 模块在通过 Protocol Layer 模块返回给用户,当返回给用户后呢,会有一个加入缓存的操作,因为其有上述说的缓存机制,至此一个 select 的查询语句的全部流程就结束了。
总结
在上述中呢,就是我们的 select 语句在 TiDB Server 层所经历的过程,值得注意的是,我们的 TiDB 还有 1 个设定就是 TiKV 的 Coprocessor:
TiKV 的 Coprocessor 又名协同处理器,它呢会帮助 TiDB 将运算下推到 TiKV 当中进行,也就是说当 TiKV 收到协同处理的请求后,会根据算子 / 数据 进行过滤 / 聚合操作,这样呢,TiDB 在收到数据之后在进行二次处理则会得出结果,大大的减轻了 TiDB 的压力。
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/df51afbb38c806f6604eac1cd】。文章转载请联系作者。
评论