数据库逻辑测试技术

参考:自动化测试数据库逻辑 Bug 的关键 —— Test Oracle - 知乎 (zhihu.com)

概述

数据库系统作为现如今大多数应用的核心,承载着数据的存取以及部分计算任务。数据库作为底层基础设施,大家普遍期望它是充分测试并可靠的。但是就跟任何一个复杂的大型软件一样,数据库也无可避免地会存在bug。而其中最危险也最让人难以捉摸的,莫过于逻辑bug了。逻辑bug,即数据库返回了错误结果。

科学的方法论以及工程化的手段是保障数据库质量的重要方式。本文重点探讨的是如何自动化测试数据库的逻辑bug。

致命的逻辑bug

不同于那些仅仅只会导致异常的 bug,数据库的逻辑bug会成功返回结果,但却是一个错误的结果。它的危害性在于,用户会误以为这是正确的结果,或者会对数据库的行为有错误的预期。这会导致重大的潜在安全隐患,比如下面MySQL的这个逻辑bug案例:

表达式:123 != NOT (NOT 123) 的计算结果应该是TRUE。所以理论上,最后的查询语句应该返回一行数据,实际却没有!

image

像这样返回错误结果的逻辑bug,很可能造成业务数据不一致。如果配合上Delete语句,甚至有可能造成所有业务数据的丢失,是非常危险的一类bug。

自动化测试的关键

逻辑bug的危险性还在于它的隐蔽性。有时候甚至需要非常复杂的表达式才能触发,又有时候相同表达式在SQL语句的不同位置计算的结果不同。所以固化的用例和手工的测试很难以有效地发现问题,那么,难道只能让用户作为那个第一个吃螃蟹的人了吗?当然不是,我们只要能够引入有效的随机化全自动测试,就能高效地发现这些逻辑bug。

但是,数据库领域的随机全自动逻辑bug测试,之前鲜有相关的研究,因为之前一直都缺位了一个理论:如何判断一条SQL语句的执行结果是正确还是失败?直到Manuel Rigger博士发表了他那3篇数据库测试论文。

数据库领域的 Test Oracles

在测试理论中,Test Oracle是一种用于判断测试用例是否执行成功的机制。最简单的Test Oracle可以是单元测试中的assert语句,其他数据库也可以作为Test Oracle。

Differential Testing

可以把相同的SQL发送给2个不同的数据库各自执行,如果结果不一致,则很有可能其中一个存在bug。这种方式被称之为Differential Testing。但是它的缺点也很明显:首先,它不满足测试理论中的Completeness和Soundness。比如,如果2个数据库存在相同的逻辑bug,它是检测不出来的。其次,虽然很早之前就出现过SQL标准,但不同的数据库仍有它们各自的SQL方言,并且在标准不明确的地方不同的数据库也有各自不同的实现。这些缺点都造成了Differential Testing测试范围的狭小以及效果不够理想。

下面,介绍3种Manuel Rigger博士提出的能够探测数据库逻辑bug的Test Oracles。

Pivoted Query Synthesis

Pivoted Query Synthesis(后简称PQS)的核心原理是:对于一行数据(称之为pivot row),会生成很多条SQL并且确保这些SQL从语义上一定能查询到这行数据,如果实际执行时发现没有查询到这条数据,则很可能是有bug存在。具体流程如下:

  1. 随机生成一些tables和rows,确保每张表都至少有一行数据
  2. 从每张表中随机选择一行数据,它们被称之为pivot row
  3. 根据pivot row中存在的列以及对应的值,随机生成结果为TRUE或者FALSE表达式
  4. 调整表达式,使它返回TRUE
  5. 生成select语句,并把刚才随机生成的表达式用在where/join语句中
  6. 执行select语句
  7. 验证pivot row在结果集中,如果不在,则说明找到了一个bug
  8. 以上是一轮测试。下一轮可以从第1步或第2步开始
image

Non-Optimizing Reference Engine Construction

Non-Optimizing Reference Engine Construction(后简称NoREC)的核心原理是:生成2条SQL,其中一条容易被优化器优化,另一条难以被优化器优化。然后比较2条SQL的查询结果,如果不同,则证明优化器可能存在bug。具体流程如下:

  1. 随机生成一些数据库/表/数据
  2. 随机生成一条查询SQL语句,记为: select * from t0 where
  3. 执行这条SQL,返回的结果集为RS
  4. 将这条SQL转换成这样的形似:select is TRUE from t0。记为SQL'
  5. 执行SQL'。返回的结果集为RS'
  6. 比较RS和RS'中数据条目的数量,如果不同,则很可能发现了一个bug
image

Ternary Query Partitioning

Ternary Query Partitioning(后简称TLP)的核心原理是:将一条查询SQL语句,分化成多条SQL语句,从语义上保证分化出来的多条SQL语句的结果集应该等于原始SQL语句。让数据库执行它们,如果它们的结果集不同,则很可能找到了一个逻辑bug。下面是具体流程:

  1. 生成一个数据库,包含一些表,以及一些数据
  2. 随机生成一条查询SQL,称之为Q。查询结果指代为RS(Q)
  3. 分化成3条查询SQL,称之为Q'(p)、Q'(not p)、Q'(p is null)。查询结果指代为RS(Q'(p))、RS(Q'(not p))、RS(Q'(p is null))
  4. 根据Q类型的不同,使用特定的表达式将Q'的3个结果集组合起来,指代为RS(Q')
  5. 判断,RS(Q)==RS(Q')。如果不相等,则很可能遇到了一个逻辑bug
image

总结

Manuel Rigger博士通过以上3种方式测试了市面上广为流行的几个数据库,如SqLite、MySQL、PostgreSQL等,一共找到了450多个bug,其中近一半是数据库的逻辑bug。从实现成本来看,PQS要求实现各个算子的计算逻辑,所以成本较高;NoREC和TLP的实现成本较低。从测试范围来看,TLP可以测试Where、Group By、Having、Distinct、Aggregate函数等场景;PQS和NoREC测试的场景范围较窄。

数据库的逻辑bug不同于执行异常,它会返回错误的结果,从而对上层应用程度埋下了重大的业务安全隐患。我们会一以贯之地通过理论与工程的结合,持续提升PolarDB-X的技术质量。

参考资料

  1. The Oracle Problem in Software Testing: A Survey
  2. Testing Database Engines via Pivoted Query Synthesis
  3. Finding Bugs in Database Systems via Query Partitioning
  4. Detecting Optimization Bugs in Database Engines via Non-Optimizing Reference Engine Construction
  5. Metamorphic Testing: A Review of Challenges and Opportunities
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容