数据库进阶测试三部曲 - 从 PQS 到 NoREC 再到 TLP

数据库进阶测试三部曲 - 从 PQS 到 NoREC 再到 TLP

一些机缘巧合,认识了在测试领域做了很深入研究的 Manuel Rigger,也读了他的三篇 Paper,算是收益匪浅吧,让我从另一个角度来思考到底我们如何更好的测试 TiDB。

PQS

PQS 的 paper 是 Testing Database Engines via Pivoted Query Synthesis,原理其实很简单的,如下图:



  1. 随机生成 table 和插入数据
  2. 从数据库中随机选择一行数据
  3. 根据这行数据,随机构造一个 expression
  4. 执行 expression,如果不为 TRUE,调整为 TRUE
  5. 将这个 expression 放到 where 或者 join 里面
  6. 执行这条查询语句
  7. 看最新的返回结果是不是还包含之前的那行数据,如果没有,则表明有 bug

是不是很简单?当时我看完这篇 Paper 之后,真的有一种『我特么怎么想不到』这种感慨,Manuel 就通过这种简单的方式给很多的数据库,包括我认为测试已经非常完备的 sqlite 找到了 bug。关于 sqlite 的测试,大家可以去看看 https://www.sqlite.org/testing.html

NoREC

NoREC 的 paper 是 Detecting Optimization Bugs in Database Engines via Non-Optimizing Reference Engine Construction,我看的时候,这篇 Paper 还是处于预览版吧,原理照样很简单:



直白的说,就是将一条优化的 Query,强制变成非优化的方式,然后对比查询结果,如果两种执行方式不一致,那就是有 bug,是不是非常的简单,是不是仍然有一种『我特么的怎么想不到』这种感慨。

相比于 PQS,NoREC 增强了对 aggregation 的判断,譬如对于 group by 等操作,可以通过一些简单的方式来验证,譬如下图使用的计数方式。



TLP

TLP 的 paper 是 Ternary Logic Partitioning: Detecting Logic Bugs in Database Management Systems,好吧,原理仍然很简单,如下图:



直白的说就是将一个 Query 分成了三个 Query,执行结果分别为 TRUE,FALSE 和 NULL,然后再将这三个 Query 的结果合并,并且保证结果为 TRUE。通过这种方式,在跟原始的结果对比,发现是否不一致。相比于 NoREC,TLP 能支持更多的 aggregation 操作,譬如:



让我很高兴的是,在 TLP 这篇 Paper 里面,Manuel 终于开始正式使用 TiDB 作为测试对象,当然帮我们发现了不少 bug,如下:



小结

Manuel 也一直在参加 TiDB 的 bug 挑战赛,他通过 sqlancer 这个工具,帮 TiDB 发现了很多 bug,现在在挑战赛排名上面也处于遥遥领先的状态,我预计第一名应该非他莫属了。另外,Manuel 也将会在 PingCAP 2020 DevCon 上面分享如何基于 TiDB 进行数据库测试,欢迎大家参与。

发布于 05-30

文章被以下专栏收录