读流程
流程概要:
用户发出sql,语句会被tidb server的Protocol layer(协议层)接收,去pd获取tso时间戳,到parse(解析模块)将sql解析为ast语法树,传给compile模块(区分点查和非点查),再到execute模块(执行器),去tikv中读取数据。数据读取回来后,交给execute模块,然后返回给Protocol layer,再给到用户。
收到执行计划后的详细流程
找到数据:
1.excutor从information schema(缓存)中获取表的元数据(表名、列名之类的对应关系)
2.excutor从pd中获取(修改的表对应的key所在的region,以及region所在的tikv的信息)
----2.1初次获取,会经过tikv client再到pd client(pd交互模块),再到pd获取信息,并缓存至tikv client的region cache中。
----2.2非初次获取,从tikv client的region cache中获取。
----2.3back off现象,region cache信息过旧,重新去pd获取数据并缓存。
3.如果是点查,直接到kv模块,然后到tikv client(交互模块),到tikv中直接读数据即可
----3.1如果不是点查,到distsql模块,将复杂的查询转换为单表的范围查询
4.tikv接受到请求,先生成snapshot(快照),作用就是10点查询,就是查10点的数据
5.请求进入unifyread pool(线程池),按照优先级去rocksdb kv中查询
数据返回:
6.tikv不一定要返回具体,有可能算子下推的功能,
--------查某个表的行数,这个表在5个tikv上,每个tikv自己算好行数,汇总到tikv server的缓存里整合,cop task(协同处理)
--------多个表在各个tikv上,只好把内容放到tidb server的tikv client的缓存中做表连接(root task)
distsql模块:
范围查询、join、子查询、表连接、嵌套查询等等,走distsql模块,将对tikv复杂的请求封装起来,提供一个简单的方法。
最终呈现:转化成多个对单表的范围查询。
写流程
流程概要:
用户发出sql,语句会被tidb server的Protocol layer(协议层)接收,去pd获取tso时间戳,到parse(解析模块)将sql解析为ast语法树,传给compile模块(区分点查和非点查),再到execute模块(执行器),去tikv中读取数据。数据读取回来后,数据放在tidb server的membuffer中,修改,然后等到用户敲了commit,开始两阶段提交。通过transaction模块(事务),将缓存中的数据写到tikv中,锁信息也写入tikv持久化。提交信息给到rocksdb kv中,然后锁信息清理,获取pd的tso。
tidb server层:
1.需要修改的数据先读入到tidb server的缓存(membuffer)中,步骤与前面一致。
2.遍历membuffer,修改数据
3.去pd client向pd申请tso(事务开始、事务提交)
4.通过kv模块,向tikv client和tikv添加数据
2.transaction模块开始两阶段提交
-------2.1将内存中修改好的数据持久化到tikv中
-------2.2将锁信息写入tikv中
-------2.3向pd获取tso
-------2.4提交信息写入tikv
-------2.5清理锁信息,等于再向tikv写入清理锁的信息
tikv层:
1.写请求发给scheduler模块,负责协调事务并发写入的冲突,并将收到的修改操作向下写入。用latch管理冲突,如果写同个key,拿到latch,可以写入,其他的写入等待。
2.raftstore模块将写请求转化为raft log。
3.raft log写入rocksdb raft中
4.leader的节点的raft的log 复制到其他节点,其他节点收到raft log,持久化到自己的raft中。
5.其他节点持久化完日志后,会返回响应值(我已经把raft log存起来了),超过一半节点返回响应,就算整个写操作commit了。(多数节点都收到了)
6.apply模块从rocksdb raft读取raft log应用到rocksdb kv。
7.反馈写入成功。