SQLSmith: Databend 如何利用随机化测试检测 Bug
作者:白 珅
Databend 研发工程师
为什么需要 SQLSmith?
在数据库系统的开发和维护过程中,测试扮演着至关重要的角色。它不仅可以验证功能的正确性,还可以发现潜在的问题,确保数据库在每个变更和迭代后保持性能和稳定性。Databend 的 CI 已经支持了多种类型的测试,主要包括:
- 单元测试(Unit Tests):用于验证代码中最小可测试单元的功能是否正常工作,主要针对函数、模块等基本功能点,确保其能够正确执行,并返回预期的结果。
- SQL 逻辑测试(SQL Logic Tests):通过 SQL 测试用例来验证 SQL 的语法和逻辑的正确性,覆盖不同的查询场景,确保查询在各种情况下都能正常运行。
- 性能测试(Performance Tests):测试新功能的性能变化,验证优化的有效性,防止性能回退。
这些测试能够保证系统在快速开发迭代过程中功能的正确性和稳定性,并覆盖常见的使用场景。但是它们也存在一些局限性,例如,测试中使用的 SQL 语句主要通过手工编写,通常较为简单,缺乏真实场景中会的出现复杂 SQL ,对各种边界条件和异常情况覆盖不足。
SQLSmith 是一个随机 SQL 查询生成器,它可以生成大量、多样化的 SQL 测试用例,从而在一定程度上模拟真实世界中的各种可能情况。相比于其它测试方法,SQLSmith 能够提高测试覆盖率,从而发现更多潜在的问题和 bug 。
SQLSmith 的实现
最早的 SQLSmith 灵感来自于 Csmith ,主要用于 PostgreSQL 的模糊测试。目前,已经有许多知名的开源数据库移植了各自版本的 SQLSmith 实现,如 CockroachDB、TiDB、RisingWave 等。
这些开源的 SQLSmith 实现使用不同的编程语言开发(包括 C++、Golang、Rust),支持的语法也各不相同,适用于各自的应用领域,我们无法直接使用它们来进行测试。为了完全支持 Databend 的语法和功能特点,我们必须用 Rust 构建自己的 SQLSmith 。
SQLSmith 主要包括三个部分,生成抽象语法树(AST)的 SQL Generator ,简化执行失败 SQL 的 SQL Reducer ,执行 SQL 并记录错误的 Runner 。
SQL Generator
SQL Generator 随机生成各种类型的抽象语法树(AST),主要包括如下几类:
- 生成多种数据类型,除了常见的基本数据类型之外,Databend 还支持了多种嵌套数据类型,包括
Array
、Map
、Tuple
等,这些类型可以多层嵌套,组合出更复杂的数据类型。 - 生成
DDL
语句,创建并修改用于测试的表,包括CREATE TABLE
,ALTER TABLE
,DELETE TABLE
等。 - 生成
DML
语句,生成随机的测试数据执行插入和修改操作,包括INSERT
,UPDATE
,DELETE
,MERGE
等。 - 生成
Query
语句,依次随机生成其内部的各个字段,包括WITH
,SelectTarget
,TableReference
,SubQuery
,ORDER ``BY
等,由于WITH
和SubQuery
包含嵌套的Query
,可以生成复杂的查询语句。 - 生成
Expression
表达式,包括Column
,Literal
,Scalar Function
,Aggregate Function
等,由于表达式的参数也可以是表达式,从而支持生成嵌套的表达式。
由于 AST 中的各个部分都会按照一定的概率随机生成,可以覆盖所有类型的 AST ,进而覆盖所有可能的 SQL 语句。通过递归调用生成器,我们还可以生成一些不常见的复杂嵌套语句,有利于发现一些隐藏的 bug 。同时,我们也需要适当控制嵌套的深度,避免生成过于复杂无法执行的 SQL。
SQL Reducer
由于 SQL Generator 生成的 SQL 语句可能会非常复杂,而造成 bug 的往往只是其中的一小部分,直接查看原始 SQL 不容易定位问题。有必要对原始 SQL 进行简化,得出能够复现该 bug 的最小 SQL,这样可以减少无关部分的干扰,方便用最简单的 SQL 复现 bug。
SQL Reducer 采用自顶向下的方法来简化 SQL,依次删除 AST 的不同组成部分,例如 WITH
,SubQuery
,Expression
等,如果删除后的 SQL 仍然可以复现出相同的 bug,我们就使用这个删除后的 SQL,否则就回退到原来的 SQL 。通过遍历 AST 的所有组成部分,最终可以得到一个最小可复现的 SQL 语句。
Runner
SQL Runner 使用 SQL Generator 按顺序不断循环生成用于测试的 SQL 语句,并连接 Databend 执行 SQL,如果执行成功则忽略,如果执行失败,说明可能存在 bug,继续按照以下流程进行处理:
- 判断是否是正常的报错,例如参数错误,语义错误等。
- 判断是否是已知的报错,例如一些未实现的功能,或已提 issue 的报错。
- 调用 SQL Reducer 进行简化生成最小可复现的 SQL 。
- 打印报错信息和简化后的 SQL 语句。
目前 Runner 已经集成到了 Databend 的 CI,在每次发布 Release 版本的时候都会执行,生成报错信息和 SQL 会被记录下来,用于进一步的分析。
SQLsmith 的效果
到目前为止,SQLSmith 已经在 Databend 运行了一个多月的时间,一共发现了 50 多个 bug,主要包括如下几类:
- 内部执行逻辑错误导致的 bug (17个)
- 函数或表达式参数校验错误导致的 bug (12个)
- 未执行正确的语义检查导致的 bug (9个)
unwrap
和unreachable
处理不当导致的 bug (7个)- Parser 语法解析失败的 bug (3个)
- 不同类型 cast 失败的 bug (4个)
- Parquet 数据读写错误导致的 bug (1个)
经验总结
通过分析 SQLSmith 发现的 bug,我们总结了一些常见的问题,可以帮助我们在以后的开发过程中避免出现 bug 。
-
函数的参数需要校验是否合法,并考虑各种情况,主要包括以下几类:
- 参数类型是
String
时,注意字符串为空的情况。 - 参数类型是
Int
时,注意值是一个大数的情况。 - 参数支持任意类型时,需要考虑一些不常用的类型,例如
Null
、EmptyArray
、Bitmap
等。 - 参数只支持特定类型时,需要考虑其它类型能不能自动转换,或者提前检查类型并返回错误。
- 参数类型是
-
谨慎使用
unwrap
,对于Result
和Option
类型的返回值,应该尽量显式的进行处理,返回值并不总是像预期的一样返回成功的结果。 -
开发新的功能需要了解相关 SQL 语义规则的约束条件,例如
ORDERBY
和HAVING
表达式中不允许出现Aggregate
和Window
函数。在 Binder 阶段进行符合语义规则的检查可以避免执行时发生错误。 -
重要的功能模块需要增加更多的单元测试用例,避免内部执行逻辑错误导致的 bug 。
下一步的工作
目前,SQLSmith 已经支持生成绝大部分常用的 SQL 并且能够与 CI 集成自动运行。我们计划在下一步继续完善 SQLsmith 的功能。主要包括如下几个方面:
- 增加更多的 SQL 语法支持,包括
Computed Column
、Union
等。 - 支持更多的配置项,包括表达式的嵌套深度,查询语句的复杂度等。
- 完善 SQL Reducer 的功能,生成更简化的 SQL 语句。
- 通过改进查询执行和结果分析的方法,提高 bug 发现的效率。
SQLSmith 是一个强大的工具,它可以帮助我们发现 Databend 隐藏的 bug,提高系统的稳定性和可靠性。我们期待 SQLsmith 在未来能够发挥更大的作用。
Connect With Us
Databend 是一款开源、弹性、低成本,基于对象存储也可以做实时分析的新式数仓。期待您的关注,一起探索云原生数仓解决方案,打造新一代开源 Data Cloud。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
深度解读MediaBox SDKs如何实现技术架构升级
本专栏将分享阿里云视频云MediaBox系列技术文章,深度剖析音视频开发利器的技术架构、技术性能、开发能效和最佳实践,一起开启音视频的开发之旅。本文为MediaBox技术架构篇,重点从音视频终端SDK的技术架构、优化设计、架构优势等方面,介绍MediaBox SDKs如何实现技术架构升级。 善师|作者 流媒体时代,越来越多的企业,投入到短视频、直播、音视频通话等相关的业务研发中来,特别是手机移动端,作为用户流量的主要入口,成为愈发激烈的流媒体竞争战场。 在此浪潮下,众多App厂商纷纷涌入音视频赛道,并且往往接入不止一个音视频业务,可能涉及直播、播放器、音视频通话等多项音视频服务。 过去,厂商在接入多个音视频业务时,通常需要接入多个音视频SDK,带来的结果是包体积极速增大,同时接入效率低下,无法做到快速上线,从而导致在竞争中错失先机。 MediaBox音视频终端SDK正是为了解决企业这一痛点而生的。 01 概念说明 MediaBox音视频终端SDK(MediaBox SDKs),以统一的技术底座,形成一系列不同能力的SDK,为客户提供灵活、易用、高效的接入体验。音视频终端SDK,与音视...
- 下一篇
🎊OpenTiny Vue 3.11.0 发布:增加富文本、ColorPicker等4个新组件,迎来了贡献者大爆发!
你好,我是 Kagol。 非常高兴跟大家宣布,2023年10月24日,OpenTiny Vue 发布了 v3.11.0 🎉。 OpenTiny 每次大版本发布,都会给大家带来一些实用的新特性,8.14 我们发布了 v3.10.0 版本,增加了4个新组件,组件 Demo 支持在 Options 和 Composition api 之间切换。 🎉OpenTiny Vue 3.10.0 版本发布:组件 Demo 支持 Composition 写法,新增4个新组件 本次 3.11.0 版本主要增加以下新组件: RichTextEditor 富文本编辑器组件 - by Caesar-ch ColorPicker 颜色选择器组件 - by GaoNeng-wWw CalendarView 日历视图组件 - by kagol Divider 分割线组件 - by vaebe 本次版本共有23位贡献者参与开发,其中有14位是新贡献者,欢迎新朋友们👏 以下是新贡献者: @jack-zishanmade their first contribution in#392 @LinboLenmade th...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Mario游戏-低调大师作品
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境