Lesca-Lee
一、概述
KaiwuDB 内核解析系列共分上下两部分,本文是该系列的第一部分,主要涵盖了网络协议到 SQL 执行器,解释 KaiwuDB 如何执行 SQL 查询,包括系统各个组件的执行路径(网络协议、SQL 会话管理、解析器、执行计划及优化、执行器、KV 引擎、事务管理等),目的是为各个组件的结构及其之间的关系提供一个高层次的统一视图。
下图是 KaiwuDB SQL 查询执行概览。左侧是 gateway 节点,负责接收 SQL Client 的 SQL 查询,生成查询计划(逻辑计划和物理计划),构造分布式执行引擎需要的 FlowSpec 并发送到被查询数据所在的节点。每个节点会根据接收到的 FlowSpec 构造物理计划中的算子并执行,然后把数据通过网络返回到 gateway 节点。接下来我们就详细讨论一下各个组件是如何工作的。

二、PostgreSQL Wire Protocol
SQL 查询通过 Postgres Wire 协议发送到 KaiwuDB(使用 Postgres 协议是为了与现有的客户端驱动和应用程序兼容)。这个组件实现了与 Postgres wire 协议相关的功能接口。用户连接后会首先进行鉴权,鉴权通过后,就会初始化一个循环,不断地读取 SQL 语句、执行并返回结果(通过封装 golang 的 net.Conn)。
PostgreSQL Wire Protocol Server 是在 KaiwuDB 启动的同时初始化的。详细的初始化流程如下图所示。首先,KaiwuDB 的 start 命令会通过 server.Start 方法调用 startServeSQL 来初始化 ServConn。ServConn 负责解析 SQL 客户端的请求、检查连接的安全性并处理连接参数,然后调用 pgServer.ServConn 方法来处理 SQL Statement。

三、SQL 执行器
接下来,serverImpl 会初始化一个 for loop 来接收 SQL 客户端的输入,直到连接关闭或者发生错误。此处的 for loop 是作为生产者,首先验证 SQL Client 的权限,通过后,会根据客户端发送的消息类型调用不同的方法。

消息类型定义请参考>>https://www.postgresql.org/docs/9.4/protocol-message-formats.html

KaiwuDB 实现了使用 tree.Statement 的子类抽象了 SQL 语句的各个子句。比如,tree.SelectClause 结构抽象了 SQL 中的 select 子句,包括 select 的 From 和 Where 子句。同时,AST 树中的许多部分会包含一个或多个 tree.Expr 结构,用来表示诸如 l_extendedprice * (1 - l_discount)这样的算术表达式。

SQL 解析成功后,会被添加到 Statement bufer 中等待执行器处理。


因为 Q7 是 select 语句,其根节点是 tree.Statement 的子类 tree.select。Q7 中每个 Statement 都被抽象为一个具体的节点,比如 ORDER BY 被表示为 tree.OrderBy,WHERE 子句被表示为 tree.Where 等。

2. SQL 语句执行

下图为 execStmtInNoTxnState 创建新事物的过程。如果当前语句是 BEGIN,则会开始一个新的事物。如果是 tree.CommitTransaction, tree.ReleaseSavepoint, tree.RollbackTransaction, tree.SetTransaction 或 tree.Savepoint 中的任何一个,则会报错;其它情况(即普通的 SQL 语句),则会转换状态机的状态到 stateOpen 并创建一个隐式事务。
