BUG标题:
事务处理过程中数据加锁不合理,导致同一数据源在交易过程中被其他交易改变
BUG影响:
1688极速到账、账期支付等场景下并发下单失败或金额占用不准确现象,造成担保方金额亏损
BUG发现过程:
1)前期参与开发代码review,梳理1688极速到账、账期支付等场景事务处理过程和锁使用机制,识别代码风险点;
2)
测试设计阶段:针对性地设计各种交易复杂场景高并发压测;
3)测试过程中:编写数据校验脚本,在上亿条日志中检查每笔交易订单正确性,并找到必现条件;
原因为:交易过程中要用到的数据源被其他买家与该卖家交易时改变,导致失败却没有进行回滚,必现条件如下图所示:
BUG解决方法:
在数据源被锁住的代码里再次添加查询剩余额度代码后再进行金额占用,并保证失败后能进行数据回滚(注:第一次查询剩余额度目的是查询需要用到几种授信源和各自的剩余金额进行数据锁定,开发认为在查询和数据锁定之间时间极短不可能发生改变,故在锁内未加入再次查询节省性能开销),同时在回归过程中评估修改影响,注意锁内操作变多带来的接口性能下降问题,经测试确实下降3MS左右幸好满足预期。
GBA传承
1、针对
数据库锁测试时,一定要考虑并发测试场景,并确保查询和使用数据源都在锁内进行,避免数据不准确;
2、性能压测过程中除了观察接口调用返回正确性,还需要观察产生的数据是否完全和预期相符,数据量大时建议用脚本或者编写小工具进行校验,在上亿条日志中不要放过任何一条可疑日志。
个人感受:
1、事务处理和数据锁相关测试,需要介入代码review,并理清各种约束条件和触发场景设计压测用例;
2、需求评估阶段单纯的认为接口压测仅需要把各种接口串联在一起进行并发测试,只需要观察接口返回正确性就OK,差点疏忽了复杂场景下接口返回是成功了但数据可能不一致的场景;
3、涉及金额的测试,出现概率就算再小也是大事,需要多留一份心。