Greenplum测试框架最全解析
软件测试是开发过程中十分重要的一环,在数据库领域更是如此。一款稳定、可靠的数据库离不开大量的测试作为支撑。
regress
-
测试用例: 一组 SQL 语句 (.sql 文件) -
期待输出:测试用例执行后, Postgres 的正确输出 (.out 文件)
isolation & isolation2
-
测试用例:一组 .spec 文件,这些 .spec 文件除了包含待测试的 SQL 语句外,最重要的是还包含了对执行这些 SQL 语句顺序的定义。 -
期待输出:测试用例的 spec 被执行后, Postgres 的正确输出 (.out 文件)。
## file: src/test/isolation/specs/deadlock-simple.specsetup{CREATE TABLE a1 ();}teardown{DROP TABLE a1;}session s1setup { BEGIN; }step s1as { LOCK TABLE a1 IN ACCESS SHARE MODE; }step s1ae { LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE; }step s1c { COMMIT; }session s2setup { BEGIN; }step s2as { LOCK TABLE a1 IN ACCESS SHARE MODE; }step s2ae { LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE; }step s2c { COMMIT; }permutation s1as s2as s1ae s2ae s1c s2c
-
s1as:对表 a1 以 ACCESS SHARE 模式上锁 -
s1ae:对表 a1 以 ACCESS EXCLUSIVE 模式上锁 -
s1c:提交当前事务
-
s2as: 对表 a1 以 ACCESS SHARE 模式上锁 -
s2ae: 对表 a1 以 ACCESS EXCLUSIVE 模式上锁 -
s2c: 提交当前事务
-
s1: 对表 a1 以 ACCESS SHARE 模式上锁 -
s2: 对表 a1 以 ACCESS SHARE 模式上锁 -
s1: 对表 a1 以 ACCESS EXCLUSIVE 模式上锁 <等待, s2 拿了 ACCESS SHARE 模式的锁> -
s2: 对表 a1 以 ACCESS EXCLUSIVE 模式上锁 <死锁发生, s1, s2 互相等待>
## file: src/test/isolation/expected/deadlock-simple.outParsed test spec with 2 sessionsstarting permutation: s1as s2as s1ae s2ae s1c s2cstep s1as: LOCK TABLE a1 IN ACCESS SHARE MODE;step s2as: LOCK TABLE a1 IN ACCESS SHARE MODE;step s1ae: LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE; <waiting ...>step s2ae: LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE;ERROR: deadlock detectedstep s1ae: <... completed>step s1c: COMMIT;step s2c: COMMIT;
CREATE TABLE a1();1: BEGIN; -- s1 开始一段事务1: LOCK TABLE a1 IN ACCESS SHARE MODE; -- s1 以 ACCESS SHARE 模式对 a1 上锁2: BEGIN; -- s2 开始一段事务2: LOCK TABLE a1 IN ACCESS SHARE MODE; -- s2 以 ACCESS SHARE 模式对 a1 上锁1&: LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE; -- s1 以 ACCESS EXCLUSIVE 模式对 a1 上锁2: LOCK TABLE a1 IN ACCESS EXCLUSIVE MODE; -- s2 以 ACCESS EXCLUSIVE 模式对 a1 上锁1<: -- 等待 s1 返回1: COMMIT; -- s1 提交事务2: COMMIT; -- s2 提交事务DROP TABLE a1;
Fault Injector
// 注: 笔者为了叙述方便, 对这里的代码进行了调整, 与实际代码可能有些出入.voidheap_insert(Relation relation, HeapTuple tup, CommandId cid,int options, BulkInsertState bistate, TransactionId xid){...#ifdef FAULT_INJECTORFaultInjector_InjectFaultIfSet("heap_insert", /*faultname*/DDLNotSpecified, /*ddlstatement*/"", /*databasename*/RelationGetRelationName(relation));#endif...}
CREATE EXTENSION gp_inject_fault;SELECT gp_inject_fault('heap_insert' /* inject location */,'infinite_loop' /* fault type */,'' /* DDL */,'' /* database name */,'my_table' /* table name */,1 /* start occurrence */,10 /* end occurrence */,0 /* extra arg */,dbid)FROM gp_segment_configuration WHERE content=1 AND role='p';
-
error:等价于 elog(ERROR) -
fatal:等价于 elog(FATAL) -
panic:等价于 elog(PANIC) -
sleep:休眠一段时间 -
suspend:阻塞当前的进程, 并且不检查中断信号 -
resume:恢复被注入 ‘suspend’ 故障的进程 -
skip:用来注入一些自定义的故障逻辑 -
reset:移除之前注入的故障 -
segv:使当前的进程崩溃 (发送 SIGSEGV 信号)
后 记
。
参考资料
郭兴,VMware Greenplum实习生
东南大学研究生在读, 2021 年 9 月加入 Greenplum 团队开启实习工作, 参与 Greenplum Extension 研发。
来一波 “在看”、“分享” 和 “赞” 吧!
本文分享自微信公众号 - Greenplum中文社区(GreenplumCommunity)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。