Parser 是 SQL 请求处理第一个模块,TiDB 每个请求需要首先进行 Parse 处理
- Parser的作用
- 校验 Sql 语法正确性
- 解析转换文本 SQL 抽象语法树
- Parse执行过程
- 词法分析
- 对Sql 进行分词,产生token流,每个token包含:
- 类型:词类型
- 词内容
- 位置信息
- 对Sql 进行分词,产生token流,每个token包含:
- 语法分析
- 消费词法分析产生的Token流,根据语法规则生成抽象语树
- Sql 语法规则校验
- 生成 AST 语法树
- 消费词法分析产生的Token流,根据语法规则生成抽象语树
- 词法分析
- 词法分析和语法分析的作用
词法分析实现
- 自研的解析器的词法分析器
- 编写 Parser.v 定义Sql 语法规则
- 使用 BNF 定义 SQL
- 可以跳过开始定义部分, Ctrl - f 搜 start: 开始查看
- 自顶向下分解定义语句,比如: select 查询由"Select" 后面跟 ‘字段列表’ 组成,字段列表由字段组成
- 通过 ‘|’ 来表达多种可能性,比如: select 查询可能加 select option 可能不加
- 语法规则后的 go 代码片段用于具体分配生成语法树,父语法通过 $N 来引用子语法产生的节点
- 通过 https://pingcap.github.io/sqlgram/ 获取更多的理解信息
- 通过 Goyacc 生成 Parser
- 编写 Parser.v 定义Sql 语法规则
- 定义“字符 -> 词法处理函数” 的映射规则(通过 Trie 保存)
- peek 字符并匹配字符调用处理函数产生Token
Syntax Error处理
- 客户端或者日志中出现错误,通过是 Parser的错误
- 检查 Mysql 的语法和语义
- 通过 Parse.y 和 sqlgram 图确认是否有兼容问题
Parser 性能问题
- 判断parser 是否有性能瓶颈
- 查看 Grafana Tidb 面板下 tidb_session_parse_duration_seconds_bucket 监控项
- 通过 go tool pprof 查看 ‘parser.Parse’ 消耗 cpu 比率
- 优化Parse 性能
- 让客户端使用并复用 PrepareStatement 避免每次 Parse
- 简化 Sql 中不必要的表达式,比如 每个列 ifnull