• Proj THUDBFuzz Paper Reading: Detecting Optimization Bugs in Database Engine via Non Optimizing Reference Engine Construction


    Abstract

    复杂的数据库优化往往会导致逻辑bugs
    本文提出NoREC(构造不优化的参照引擎)算法
    主要方法: 将query返回值与不加优化的dbms返回值之间的差异做对比
    困难:DBMS实现方式很多,难以直接获取不加优化的执行结果
    Solution: 将原查询重写为一个无法进行优化必须每行查询的格式
    实验:

    • 对象: PostgreSQL, MariaDB, SQLite, CockroachDB
    • 结果: 159个新bugs(其中141个已经fixed)
      - 51个optimization bugs
      - 108个其他bugs或者crash bugs

    Intro

    已有工作

    1. 作者之前的工作Pivoted Query Synthesis
      • 问题: 只能考虑1行,无法找到类似不该重复读取的记录重复读到了的情况
    2. RAGS: 用多个DBMS验证当前DBMS
      • 问题: DBMS方言不同,只能验证每个DBMS都支持的核心SQL

    本文工作

    提出了NoREC,将带where的Query转化为检查每行record是否符合where子句的query,使得原query中获得的数据条数相当于改后query查询到的true的个数

    例子如下:

    在SQLITE中, query1没能读到数据,但是经过改变的query2读到了数据,因此检查出bug

    Background

    本文工作无法用来测试No-SQL,因为这些数据库不能完整支持SQL语法,但是可以用来测试NewSQL,因为NewSQL尝试实现NoSQL同等的scalability同时兼容SQL语法

    目前已有的一些测试思路:
    Automatic testing: 关键在于test case和test oracle
    Optimizations in DBMS: Each DBMS typically provides a query optimizer that inspects a query, potentially simplifies it, and maps it efficiently to physical accesses.
    Differetial Testing: RAGS类似的思路。Slutz实现了RAGS的思路
    Controlling optimization in DBMS: 对比优化前后的执行结果,在编译器测试上已有使用,但是在DBMS上,大部分的优化没法自动关闭

    Approach

    基本流程:

    3.2 Translating the Query

    当将原Query翻译为非优化Query时,除了简单的where语句移到select后面,还有如下拓展可以使用:

    1. 从多个表中读取
    2. join子句:join子句可以直接在非优化query中被拷贝,保持不变,当然,移动到on子句也是一种方法
    3. order by: 在非优化query中可以直接忽略
    4. group by: 需要添加一个query来读中间结果的counts

    3.3 Determining the Row Count

    计算原查询条数有两种方式1. 直接iterate 2. 使用aggregate function,如count。这两种是混用的
    本文也思考过是否要比对原查询和实际查询的实际内容,然而作者的经验是这种bug是比较少见的,因此本文只对比返回数据的条数

    3.4 Corner Cases and Limitations

    本节探讨了本文没法覆盖到的bugs类型,以及三个看似bug但是数据库不认为是bug因此可以放在那里不管的corner cases

    Ambigious queries

    有些查询本身就有二义性,优化或者非优化返回的结果虽然不一样,但是合法,比如subqueries
    措施: 不生成subquery

    Nondeterministic functions

    措施: 避免和随机数或者当时时间有关的查询

    Other features

    措施: 避免处理distinct子句和在多条记录上计算结果,比如aggregate或者window functions

    Corner case1: Number comparison in SQLite

    在sqlite中使用distinct会认为浮点数和与其值相同的整数,比如0.0和0,认为是同一个数。query1中获取到的就是0这条记录,v0.c0 0.1经过拼接得到0.01,在条件中对应TRUE,但是query2中获取到的就是0.0这条记录,v0.c0 0.1经过拼接得到0.00.01,在条件中对应False。

    Corner case2: Input Columns in SQLite

    如果把stat.aggregate放在where子句中,就会使得conf option中对应值为True,但是在select子句中则不会

    Corner case3: Ambigious group bys

    在SQLite中group by具有二义性,与optimizer hint,比如unlikely连用时会导致bug。
    Q: 具体是什么样的二义性?

    3.5 Query and Database Generation

    用SQLancer

    4 Evalutation

    4.1 Methodology

    1. 为什么选这四个数据库来测试
    2. 测试过程中付出的精力不同的原因:有些回复及时,测得比较深入
    3. 这些数据库自身已有的测试,如SQLITE已经实现了条件100%覆盖,还写了自身的out-of-memory testing, IO error testing, crash testing, 组件失效testing, fuzz testing, dynamic analysis。CockroachDB已经有一个基于SQLSmith改编的用go实现的query generator
    4. 测试方法: 测试时是有软件开发者和自身的反馈,一轮轮迭代产品Sqlancer,此外,使用了C-reduce来尽量生成可理解的bug重现。

    4.2 Selected Bugs

    bug举例

    4.3 Bugs Overview

    找到了多少bug,多少个被comfirmed, 多少个被fixed,多少个是逻辑bugs,多少个是顺带得到的crash bugs,比如与order by相关的bug有多少,具体的软件版本

    4.4 Comparison to PQS

    对比难点,方法(如何将NoREC的有用测试用例转为PQS的,反之亦然),只被NoREC覆盖的bugs比,各自发现的bug种类

    5 Discussion

    1. DBMS开发者对本软件的反馈
    2. Bug importance: 承认发现的不少bugs是程序员不太可能会写的SQL,但是即使是这种bugs,考虑到SQL生成器/code generator的存在,也是有可能自动生成的。
    3. Handling of joins: 现在已经够用,但是TODO WORK
    4. Code coverage: 认为高的代码覆盖率并不一定特别重要
    5. bugs种类: 认为不被发现的logic bugs才是更可怕的
  • 相关阅读:
    安装 macbook 双系统( OS X 和 Ubuntu )
    微信小程序初探
    [Javascript] Promise
    [AS/400] 基本概念
    [AS/400] Control Language(CL) 基本概念
    [AS/400] Control Language
    [github] 创建个人网页
    [tools] sublime 使用记录
    [Java] TreeMap
    exe转msi
  • 原文地址:https://www.cnblogs.com/xuesu/p/14156850.html
Copyright © 2020-2023  润新知