美文网首页
详细解读TPCC事务测试方法

详细解读TPCC事务测试方法

作者: 失速的脑细胞 | 来源:发表于2018-06-22 15:37 被阅读324次

    (注:本文共4500余字,大约阅读时长为15分钟)

    一、成文背景

    最近在制定分布式事务数据库的测试方法过程中,一个令人头疼的问题就是如何能够验证一个事务系统的ACID属性满足情况。

    因为一个分布式事务数据库系统ACID属性是否满足并不是像吞吐量、事务时延等显而易见,它通常需要在组合型业务负载并发或某些特殊环境下才能被“成功”暴露。这些组合型业务通常需要满足例如固定的先后顺序、一定的并发规模或者是特殊的异常情况,有的时候真的是“可遇不可求”,所以对于线下验证实在是一个很大的障碍。

    通常追求“短平快”的互联网业务会找到一个暴力解决方案,即利用真实的线上流量复制,通过系统产生的错误数来验证系统是否满足事务能力。这类方法的确比较有效,但是也存在严重的缺点。首先并不优雅;第二没办法大面积推广,毕竟业务是各公司独立的;最后是对交付结果的不够负责,如果该系统只是服务内部业务还好,如果需要作为产品对外输出,那就是拿着脆弱的公司信誉去豪赌了。

    相关资料在公开网站并不多,所以笔者最近研究了下原有单机事务数据库最出名的测试基准TPCC中的事务能力验证方法,总结成文,希望能够对有同样困扰的人员有所帮助。

    首先简单介绍下TPCC。TPCC是TPC组织联合Oracle、IBM、思科等企业制定的单机事务数据库测试基准。它模拟了一个仓储物流的业务场景,包括新建订单、付款、发货、订单查询、库存查询五个事务操作。执行TPCC测试程序,将会得到被测系统的吞吐量、时延、事务完成数等信息,详细细节读者可自行谷歌百度,本文主要介绍其事务衡量方法,其他内容不做过多介绍。

    TPCC分别针对事务能力的ACID属性,分为四类测试方法,下文将一一介绍。

    二、TPCC原子性测试

    定义:系统需要保证一个事务内的动作要么全部执行,要么全部不执行。

    测试方法分为两种:

    (1)通过顾客编号,随机选择仓库、区域和顾客执行付款操作,并检查顾客、区域和仓库表中的数据是否被正确改变。

    (2)通过顾客编号,随机选择仓库、区域和顾客执行付款操作,并提交回滚命令。检查顾客、区域和仓库表中的数据并没有被改变。

    三、TPCC一致性测试

    定义:

    系统需要在任何时刻总是保持一致的状态,变化只能从一个一致态到另一个一致态。

    说明:

    TPCC定义了十二个条件,用来衡量系统是否满足一致性。如果数据库系统中有数据的备份,那么备份的数据也需要满足。在这十二个条件中,前四个条件是必须满足的。

    一致性条件1:

        涉及warehouse和district两张表。

        连接条件W_IUD=D_W_ID。

        验证条件为W_YTD = sum(D_YTD)

    一致性条件2:

        涉及district、order和new-order三张表。

        连接条件为D_W_ID = O_W_ID = NO_W_ID && D_ID=O_D_ID=NO_D_ID

        验证条件为D_NEXT_O_ID-1 = max(O_ID)= max(NO_O_ID)

    一致性条件3:

         涉及new-order,district两张表。

         连接条件为单一district下的NO_W_ID和NO_D_ID.

         验证条件为max(NO_O_ID)-min(NO_O_ID) + 1 = [该district内的new-order记录条数]

    一致性条件4:

         涉及order、oder-line和district两张表

         连接条件为单一district下的O_W_ID=OL_W_ID &&O_D_I=OL_D_ID

         验证条件为sum(O_OL_CNT) = [该district下的order-line的所有记录条数]

    一致性条件5

         涉及order,new-order两张表

         连接条件为(o_w_id,o_d_id,o_id)=(no_w_id,no_d_id,no_o_id)

         验证条件为o_carrier_id !=null

    一致性条件6

         涉及Order,order-line两张表

         连接条件为(O_W_ID,O_D_ID,O_ID)=(OL_W_ID,OL_D_ID,OL_O_ID)

         验证条件为O_OL_CNT = [ORDER_LINE的所有记录条数]

    一致性条件7

         涉及ORDER-LINE,ORDER两张表

         连接条件为(O_W_ID,O_D_ID,O_ID)=(OL_W_ID,OL_D_ID,OL_O_ID)

         验证条件为OL_DELIVERY_D = O_CARRIER_ID = null

    一致性条件8

         涉及WAREHOUSE,HISTORY两张表

         连接条件为W_ID = H_W_ID

         验证条件为W_YTD = sum(H_AMOUNT)

    一致性条件9

         涉及DISTRICT,HISTORY两张表

         连接条件为(D_W_ID,D_ID)= (H_W_ID,H_D_ID)

         验证条件为D_YTD = sum(H_AMOUNT)

    一致性条件10

          涉及CUSTOMER,HISTORY,ORDER和ORDER-LINE四张表

          连接条件

               (1)(C_W_ID,C_D_ID,C_ID) = (H_C_W_ID,H_C_D_ID,H_C_ID)

               (2)(OL_W_ID,OL_D_ID,OL_O_ID)= (O_W_ID,O_D_ID,O_ID) &&

                          (O_W_ID,O_D_ID,O_C_ID) = (C_W_ID,C_D_ID,C_ID)&&

                         (OL_DELIVERY_D != null)

           验证条件为C_BALANCE = sum(OL_AMOUNT) – sum(H_AMOUNT)

    一致性条件11

           涉及CUSTOMER,ORDER和NEW-ORDER三张表

           连接条件(O_W_ID, O_D_ID)= (NO_W_ID,NO_D_ID) =(C_W_ID,C_D_ID)

           验证条件为(count(*) from ORDER) – (count(*) from NEW-ORDER) =2100

    一致性条件12

         CUSTOMER,ORDER-LINE两张表

         连接条件 OL_DELIVERY_D !=null

         验证条件为C_BALANCE +C_YTD_PAYMENT = sum(OL_AMOUNT)

    测试方法:

    首先确认数据库初始状态满足上述一致性条件,之后提交事务操作,并执行最少五分钟,同时在执行过程中最少设置一个检查点用来验证一致性。

    在五分钟执行完毕后,再次利用上述一致性条件验证系统状态。

    四、TPCC隔离性测试

    说明:

    即检测脏写、脏读、不可重复读、幻读四种可能出现的异常情况。

    同时对于TPCC场景内的各类业务,定义new-order事务为T1,Payment事务为T2,Delivery事务为T3,Order-Status事务为T4,Stock-Level事务为T5,其余事务为Tn

    定义Level 0 为读未提交,level 1为读已提交,level 2为可重复读,level 3位序列化

    测试方法:

    1、验证T1和T4事务的读写冲突中的隔离情况。

    (1)开启T1事务

    (2)在提交之前暂时停止T1事务

    (3)开启T4事务,查询条件同步骤1中的T1

    (4)确认T2等待

    (5)完成T1,同时确认T2是否完成

    (6)确认T2查询结果与T1插入结果相同

    2、验证T1和T4事务在回滚情况下的读写冲突隔离情况。

    (1)执行一个T4事务,并执行完成

    (2)开始一个条件与步骤1中相同的T1事务

    (3)在提交之前暂停T1事务

    (4)再次启动一个T4事务,条件同步骤1

    (5)确认T4事务等待

    (6)回滚T1事务,并确认T4事务完成

    (7)确认T4事务返回结果与步骤1相同

    3、验证两个T1事务的写写冲突隔离情况。

    (1)开始第一个T1事务

    (2)在第一个T1事务提交之前暂停

    (3)开始与第一个T1事务条件相同的第二个T1事务

    (4)确认第二个T1事务等待

    (5)完成第一个T1事务。同时确认第二个T1事务应该完成。

    (6)确认第二个T1事务的返回结果大于第一个T1事务的返回结果。同时确认D_NEXT_O_ID字段记录了第一个和第二个T1事务的结果。

    4、验证两个T1事务在其中一个回滚情况下的写写冲突隔离情况。

    (1)开始包含不可用元素的第一个T1事务

    (2)在第一个T1事务即将回滚的时候暂停

    (3)开始与第一个T1事务条件相同的第二个T1事务

    (4)确认第二个T1事务等待

    (5)执行完成第一个T1事务。同时确认第二个T1事务完成

    (6)确认第二个T1事务返回值大于之前的订单号。确认D_NEXT_O_ID只反映了第二个T1事务。

    5、验证T2事务和T3在写写冲突情况下的隔离情况。

    (1)开始一个T3事务

    (2)在T3事务提交之前暂停

    (3)开始一个T2事务,执行条件等同于步骤1中的T3事务

    (4)确认T2事务处于等待状态

    (5)使T3事务完成。确认T2事务也完成。

    (6)确认C_BALANCE正确反映了T1和T2事务的结果。

    6、验证T2事务和T3事务在T3回滚的情况下的写写冲突隔离情况。

    (1)开始一个T3事务

    (2)在T3事务提交之前暂停

    (3)开始一个T2事务,执行条件等同于步骤1中的T3事务

    (4)确认T2事务处于等待状态

    (5)对T3事务执行回滚操作。确认T2事务也已经完成

    (6)确认C_BALANCE反映了T2事务的正确结果

    7、验证交互式事务更改项目价格时的,T1事务的重复读能力。预先给出x和y两个随机的项目编号。

    (1)开始一个事务。查询x和y的I_PRICE。提交T1事务。

    (2)开始一个T1事务,查询包括x和y的一系列项目的价格。

    (3)当T1事务第一次查询完x项目的价格后,在查询y项目以及执行第二次查询a项目操作前,暂停T1事务

    (4)开始一个事务,将x和y项目的价格提交10%

    (注:以下ABCD任意情况执行成功即可,同时需要注意数据副本需保持一致)

    情况A,如果步骤4事务卡住了:

    5A. 继续T1事务,并且确认项目x的价格和y的价格与步骤1中的查询结果相同,并提交T1事务

    6A. 确认步骤4中的事务完成并且被提交

    7A. 开始一个事务,查询项目x和y的价格,并提交

    8A. 确认7A步骤中查询出的价格与步骤4设置的价格相同

    情况B,如果步骤4事务并没有卡住,而T1事务进行了回滚

    5B. 确认步骤4中的事务完成并且被提交

    6B. 继续T1事务,并确认它已经被数据管理中心指定为回滚操作

    7B. 开始一个事务,查询项目x和y的价格,并提交

    8B. 确认7B步骤正查询的价格与步骤4中更改的价格相同

    情况C,如果步骤4中的事务被回滚

    5C. 确认步骤4中的事务被数据管理中心指定为回滚操作

    6C. 继续T1事务,并且确认项目x的价格和y的价格与步骤1中的查询结果相同,并提交T1事务

    7C. 开始一个事务,查询项目x和y的价格,并提交

    8C. 确认步骤7C中查询的结果与步骤6C中相同

    情况D,如果步骤4中的事务没有卡住,并且没有任何事务回滚

    5D. 确认步骤4中的事务完成并且被提交

    6D. 继续T1事务,并且确认项目x的价格和y的价格与步骤1中的查询结果相同,并提交T1事务

    7D. 开始一个事务,查询项目x和y的价格,并提交

    8D. 确认7D步骤查询的价格与步骤4中更改的价格相同

    8、验证是否能够在T1事务和T3事务之间防止幻读现象的产生。

    (1)从NEW-ORDER表中,随机挑选一个区域和仓库,并删除其所有数据

    (2)在选中的仓库中,开启一个T3事务

    (3)在NEW-ORDER表中读取一个选中区域的数据后,暂停T3事务。此时应该没有数据被读出

    (4)使用相同的仓库和区域参数开启一个T1事务

    (注:除了下列AB情况,仍然可能发生其他情况)

    情况A,如果T1事务卡住了:

    5A. 通过重复读取NEW-ORDER表中选中区域的数据,继续T3事务

    6A. 确认此时还是没有数据被读出

    7A. 完成提交T3事务

    8A. 确认T1事务执行完成了

    情况B,如果T1事务没有被卡住:

    5B. 完成提交T1事务

    6B. 通过重复读取NEW-ORDER表中选中区域的数据,继续T3事务

    7B. 确认此时还是没有数据被读出

    8B. 完成提交T3事务

    9、验证是否能够在T1事务和T4事务之间防止幻读现象的产生。

    (1)根据选好的用户开始T4事务

    (2)从ORDER表中查询选好用户的记录之后,暂停T4事务。此时该用户最新的订单应该被查到

    (3)对该用户启动T1事务

    (注:除了下列AB情况,仍然可能发生其他情况)

    情况A,如果T1事务卡住了:

    4A. 通过重复的读该用户的ORDER表继续T4事务

    5A. 确认得到的结果跟步骤2相同

    6A. 完成提交T4事务

    7A. 确认T1事务提交完成

    情况B,如果T1事务没有卡住:

    4B. 完成提交T1事务

    5B. 通过重复的读该用户的ORDER表继续T4事务

    6B. 确认返回的结果与步骤2相同

    7B. 完成提交T4事务

    五、TPCC持久性验证

    定义:

    即保证已提交的事务影响的持久性,并且需要保证数据库在各类异常发生下的一致性保证能力。

    说明:

    没有系统能够保证完整的持久性,即所有异常情况下的持久性。本次测试的异常情况包括

    (1)不可恢复的单点存储介质故障,且该存储介质应该存储了影响数据库数据的内容

    (2)能够造成事务失败的系统或子系统的故障

    (3)部分或全部的内存故障

    (4)数据库系统整体掉电

    测试方法:

    总体测试方法就是保证各类事务在多种异常情况下能够在终端或其他结果显示的地方展示出正确结果,并且系统在恢复后依然处于一致性状态。

    测试过程需要实现说明中的各类异常,并且同时有一定的业务负载。

    对于每一种异常情况,测试步骤如下:

    (1)在DISTRICT表中计算所有行的D_NEXT_O_ID和,从而记录当前总订单数count1.

    (2)启动TPCC业务负载,并且至少持续5分钟。同时在驱动系统successfile内,记录成功或回滚的New-Order事务数

    (3)制造异常

    (4)启动数据库恢复机制

    (5)比较驱动系统successfile内的记录数与数据库系统内的order表相应记录一致

    (6)重新执行步骤1,记录当前order总记录数count2,确认count2-count1>=successfile记录数。如果两者不相等,那么ORDER表需要有附加记录(原因是因为有的记录虽然提交了,但是由于系统损坏,终端没显示)。

    (7)通过一致性测试3中的测试方法验证当前系统是否处于一致性状态。

    六、总结

    在TPCC的ACID属性验证中,总体原则依然是依靠自身业务场景,构造并发和锁情况的多种组合,为事务能力测试提供了思路。

    但是由于在分布式环境中,并发业务涉及到的数据分片以及通讯交互更加复杂,未来仍然需要进行重点的研究探索。

    七、广告

    前段时间信通院与支付清算协会牵头,组织国内最顶尖的厂商和银行联合编写了《金融分布式事务数据库白皮书》,里面有更多详细的产业、技术报告和观点,大家可以联系我获取电子版。

    同时我们信通院已经开始着手新一代数据库基准研究工作,力图实现“国际分布式数据库第一把尺子由自主掌控”的愿景,已经基本完成了功能测试办法,正在制定性能测试方案及工具,欢迎有兴趣的厂商和人员与我联系。

    最后声明,文中的观点、数据、图片均可引用,我们信通院将会一直秉持开放的理念,但希望同时能够介绍下我们的工作,让更多的人与我们一起来完成有意义的事情。

    相关文章

      网友评论

          本文标题:详细解读TPCC事务测试方法

          本文链接:https://www.haomeiwen.com/subject/ykfkyftx.html