【学习笔记】TiDB Parser

Parser 是 SQL 请求处理第一个模块,TiDB 每个请求需要首先进行 Parse 处理

  • Parser的作用
    • 校验 Sql 语法正确性
    • 解析转换文本 SQL 抽象语法树
  • Parse执行过程
    • 词法分析
      • 对Sql 进行分词,产生token流,每个token包含:
        • 类型:词类型
        • 词内容
        • 位置信息
    • 语法分析
      • 消费词法分析产生的Token流,根据语法规则生成抽象语树
        • Sql 语法规则校验
        • 生成 AST 语法树
  • 词法分析和语法分析的作用

词法分析实现

  • 自研的解析器的词法分析器
    • 编写 Parser.v 定义Sql 语法规则
      • 使用 BNF 定义 SQL
      • 可以跳过开始定义部分, Ctrl - f 搜 start: 开始查看
      • 自顶向下分解定义语句,比如: select 查询由"Select" 后面跟 ‘字段列表’ 组成,字段列表由字段组成
      • 通过 ‘|’ 来表达多种可能性,比如: select 查询可能加 select option 可能不加
      • 语法规则后的 go 代码片段用于具体分配生成语法树,父语法通过 $N 来引用子语法产生的节点
      • 通过 https://pingcap.github.io/sqlgram/ 获取更多的理解信息
    • 通过 Goyacc 生成 Parser
  • 定义“字符 -> 词法处理函数” 的映射规则(通过 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
1 个赞