一些机缘巧合,认识了在测试领域做了很深入研究的 Manuel Rigger,也读了他的三篇 Paper,算是收益匪浅吧,让我从另一个角度来思考到底我们如何更好的测试 TiDB。
PQS
PQS 的 paper 是 Testing Database Engines via Pivoted Query Synthesis,原理其实很简单的,如下图:
- 随机生成 table 和插入数据
- 从数据库中随机选择一行数据
- 根据这行数据,随机构造一个 expression
- 执行 expression,如果不为 TRUE,调整为 TRUE
- 将这个 expression 放到 where 或者 join 里面
- 执行这条查询语句
- 看最新的返回结果是不是还包含之前的那行数据,如果没有,则表明有 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 进行数据库测试,欢迎大家参与。