#BUG SHOW# 嵌套事务业务场景测试札记

文摘   2024-06-16 11:07   四川  
最近出了一个bug,比较神奇的是,竟然一年前的变更引起的。为什么一年了,最近才出现首笔异常流量?最终推测可能是上半年的一次任务挤压有关,导致了这次黑天鹅事件。
切入正题之前还是有必要介绍一下事务相关的知识。事务、嵌套事务、分布式事务。
01/事务相关知识
事务(Transaction)是数据库操作的基本单位,用于保证数据的一致性、完整性和隔离性。在计算机科学中,特别是在数据库管理和编程领域,事务的概念极其重要。

1.1. ACID

  1. 原子性(Atomicity):事务是一个不可分割的工作单位,事务中的所有操作要么全部执行成功,要么全部不执行(即回滚)。如果事务中任何一部分失败,整个事务都会被回滚,就像从未发生过一样。
  2. 一致性(Consistency):事务执行前后,数据库的状态必须从一种合法状态转换到另一种合法状态。这意味着事务必须遵循所有的数据完整性规则,如实体完整性、参照完整性和用户定义的完整性约束。
  3. 隔离性(Isolation):多个事务并发执行时,彼此间不应互相影响。事务的隔离级别决定了一个事务可以看到其他事务修改数据的程度,从最低级的读未提交(Read Uncommitted)到最高的串行化(Serializable),隔离级别越高,并发性能越低,但数据一致性越好。
  4. 持久性(Durability):一旦事务被提交,它对数据库的改变就是永久性的,即使系统出现故障,事务的效果也不能丢失。

1.2. 生命周期

  • 开始事务:通常通过编程语言提供的API或SQL语句显式声明事务的开始,如BEGIN TRANSACTION。
  • 执行操作:在事务开始和结束之间,可以执行一系列数据库操作,如INSERT、UPDATE、DELETE等。
  • 提交事务:如果所有操作成功完成,通过COMMIT语句提交事务,将更改永久保存到数据库。
  • 回滚事务:如果在事务过程中发生错误,可以通过ROLLBACK语句撤销事务中所有已完成的操作,恢复到事务开始前的状态。

1.3. 分类

  • 简单事务:在一个数据库实例内进行的事务操作。
  • 分布式事务:微服务架构下,原子服务(拥有自己的部署容器和数据存储容器)部署在不同的服务器上,服务间调用就会出现跨越多个数据库或服务的事务,需要特殊的协调机制(如两阶段提交)来确保所有参与方的一致性。
  • 嵌套事务:在一个事务内部再启动新的事务,通过事务传播行为控制内部事务与外部事务的关系。

1.4. 实现技术

  • 两阶段提交(2PC):一种经典的分布式事务协调协议,分为预提交和提交两个阶段,确保所有参与节点达成一致决策。
  • 三阶段提交(3PC):在2PC基础上改进,增加了预预提交阶段,减少阻塞范围,提高系统可用性。
  • Saga模式:通过一系列有事务补偿操作的业务步骤来模拟长事务,支持最终一致性,适用于微服务架构。
  • 乐观锁与悲观锁:在并发控制中用于解决事务间的冲突,乐观锁假设并发冲突较少,悲观锁则假设冲突频繁。
事务管理是构建可靠和高性能应用程序的基础,正确设计和应用事务策略对于保证数据的准确性和完整性至关重要。
02/缺陷分析

2.1. 业务场景

我画了个简图,大家先凑合着看,应该是比较浅显易懂的 。😂
我们的服务有个业务逻辑,由两个事务组成:
  • transaction 1 会落table A 一条 A数据,然后将内容塞入上下文,供transaction 2使用。然后会发一条消息。然后执行 transaction 2。
  • transaction 2 首先判断上下文内容是否存在A数据,如果存在,则继续insert table B一条数据B;反之,则直接return,不做什么操作。
23年出现了一个线上问题,具体问题是:幂等场景下,会重复发消息,导致下游重复监听。
为了解决这个缺陷做了个代码优化,具体变更点:
  • 就是加了个幂等判断,见蓝色代码。查询A数据是否已经落单,若落单则直接return,不发消息,继续执行transaction 2;反之会发消息,执行transaction 2。

2.2. 测试验证

当时验证比较简单,是直接在场景A正常执行的落的数据基础上 手动改 table A 数据 A然后发起幂等测试,断言幂等发起后,不重复发消息。

2.3. 触发缺陷

最近一次缺陷是,transaction 1执行成功后transaction 2 执行失败了,没有落 table B数据B
触发自动重试,由于在transaction 1处幂等拦截掉直接return,导致transaction 2在获取上下文信息是null,也直接return了。最终导致场景A落的数据不完整,没有继续推进下一阶段。

2.4. 测试复盘

虽然这个缺陷是黑天鹅事件,但是仍然属于测试遗漏,在分析测试场景的时候出现了想当然,没有深入了解transaction 2。如今分析代码后,重新对测试点进行梳理如下:
后话:幂等场景看似简单,实则细节满满,稍不留意就有可能踩坑。究其根因,无非是大家处理“寻常”事时候经验(感性)占上风,缺乏理性的分析。就像大家都知道1+1=2,但是很少去理性分析为什么1+1=2。
毋以小而不为”。


往期系列文章
阿里微服务质量保障系列:微服务知多少
阿里微服务质量保障系列:研发流程知多少
阿里微服务质量保障系列:研发环境知多少
阿里微服务质量保障系列:阿里变更三板斧
阿里微服务质量保障系列:故障演练
阿里微服务质量保障系列:研发模式&发布策略
阿里微服务质量保障系列:性能监控
阿里微服务质量保障系列:性能监控最佳实践
阿里微服务质量保障系列:基于全链路的测试分析实践
- END -


下方扫码关注 软件质量保障,与质量君一起学习成长、共同进步,做一个职场最贵Tester!

往期推荐

聊聊工作中的自我管理和向上管理

经验分享|测试工程师转型测试开发历程

聊聊UI自动化的PageObject设计模式

细读《阿里测试之道》

我在阿里做测开

软件质量保障
所寫即所思|一个阿里质量人对测试技术的思考。
 最新文章