以下内容参考Python 测试之道与https://www.jianshu.com/p/58d52635b7cc
接口并发测试是以并发为手段的测试行为,通过测试行为发现接口在并发场景下的接口问题
并发测出的问题常常是多种错误交织在一起,发现并解决此类问题通常为以下5个步骤
- 通过并发测试找到故障点
- 以故障点的现象发现问题的原因
- 确定原因后讨论解决方案
- 根据解决方案修复问题
- 通过并发测试验证修复的情况
常见的并发问题有以下三类
- 事务并发问题
- 极限值并发问题
- 压力并发问题
以下进行逐一说明
一、事务并发问题
事务的定义:我们都知道事务是一组单元化的操作,这组操作可以保证要么全部成功,要么全部失败;或者只要其中某个操作失败,就会把之前已经成功的操作进行回滚,以此来保证数据的完整性。
以下几个是事务的四个特性:
- 原子性操作:一个事务里面的操作,要么都做,要么都不做
- 状态保存一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态
- 隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
以手机购买电影票为例,电影票购买流程为:选择一部电影–>选择座位–>确认选座–生成订单–>进入支付—选择支付方式–>选择优惠活动–支付订单成功–>通知商场支付结果
以上流程分成2个事务,事务1:选座+生成订单,事务2:支付订单
以事务1为例,事务四个特性可解释如下:
- 原子性操作:要么选座生成订单,要么没有选座也没有生成订单
- 状态保持一致性:系统锁定座位时必须生成订单,用户取消订单后必须解锁座位
- 隔离性:座位只能有1个人选定,不能被别人选定
- 持久性:生成订单后订单存在不会丢失,修改订单状态需要另起一个事务
违反这些特性可能出现的问题,就是测试事务并发时所需要考虑的测试点:
- 1个座位被多个人锁定并生成了订单
- 座位锁定成功但没有生成订单
- 订单取消成功但解锁座位失败
- 生成重复的订单号
- 操作日志没有完整记录操作行为
二、极限值并发问题
由于极限值而导致的并发问题,什么是极限值呢,极限值就是达到限定的值,比如:商场举行营销活动,每人每日可获取2次抽奖机会,转发朋友圈增加一次抽奖机会,已经获得一等奖二等奖的用户不能再获得三等奖和四等奖,中奖概率按照估算概率进行设定,中奖数量达到上限,则该奖项停止,这个例子进行拆分场景如下:
1. 每人每日获得2次抽奖机会
2. 转发朋友圈额外获得一次抽奖机会
3. 已经获得一等奖二等奖的用户不能再获得三等奖和四等奖
4. 中奖概率按照估算概率进行设定
5. 中奖数量达到上限,则该奖项停止
以上场景涉及的测试对象包括:抽奖次数,抽奖概率,奖品数量上限,抽奖规则
针对这些测试对象,分析这些对象如有越界导致的问题作为并发测试点
1. 转发朋友圈获得的抽奖机会超过1次
2. 每日抽奖次数超过上限
3. 中奖概率分配不足100%或超过100%
4. 奖品数量达到上限
5. 已经获得一等奖和二等奖的用户能否再中奖
以上及极限值并发问题分析方法
三 压力并发问题
由于压力负载导致的并发问题,此类问题可以归类于性能问题,做压力测试,除了能发现系统中的性能问题,也能发现系统功能上的缺陷。做此类测试,需要了解数据库事务隔离的知识
数据库事务隔离级别有4个,由低到高如下:
- Read uncommitted(未授权读取,读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”实现,该隔离级别避免了更新丢失,却可能出现脏读,也就是事务B读取到了事务A未提交的数据 - Read commited(授权读取,读提交)
读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,却可能出现不可重复读。即事务A事先读取了数据,紧接着事务B更新了数据并提交了事务,而事务A再次读取该条数据时,数据已经发生的变化 - Repeatable read(可重复读取)
读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。该隔离级别避免了不可重复读和脏读,但是有时可能出现幻读 - Serializable(序列化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接一个执行,但不能并发执行。序列化是最高级别的事务隔离,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务序列化执行,避免了脏读,不可重复读和幻读
通常数据库默认设置隔离级别为 Read uncommitted,仅支持使用事务并防止脏读,事务隔离级别越高,性能越差,当项目需求对性能有要求时,就不能通过提高数据库设置级别保证并发事务处理的正确性。为了保证系统性能不受应用,大部分业务隔离将由程序逻辑进行处理
名词解释:
- 脏读:一个事务读取到了另一个事务未提交的数据
- 更新丢失:
(1)回滚丢失:当2个事务更新相同的数据源时,如果第一个事务被提交,而另外一个事务却被撤销,那么会连同第一个事务所做的更新也被撤销,就是说第一个事务的更新丢失了
(2)覆盖丢失:当2个或多个事务查询同样的记录然后各自基于最初的查询结果更新该行时,会造成覆盖丢失,因为每个事务都不知道其他事务的存在,最后一个事务对记录做的修改将覆盖其他事务对该记录做的提交的更新 - 不可重复读:一个事务对同一行数据重复读取2次,但是确得到不通的结果
(1)虚读:事务T1读取某一行数据后,事务T2修改了该条数据,事务T1再次读取该数据时得到与前一次不同的值
(2)幻读:事务在操作过程中进行了两次查询(不要求2次查询的SQL一样),第二次查询结果包含了第一次查询结果中未出现的数据或者缺少了第一次查询结果中的数据。这是由于两次查询结果过程中有另外一个事务插入数据导致的