背景:生产环境出现写成功,接口却返回失败的场景
分析:先确认是否如他们反馈的现象一致,查询日志确认一致;接口进入和返回失败的时间间隔发现是5秒,与设置的接口超时时间一致,分析大概率是超时了,内部具体日志分析,定位到入库的事务执行耗时6秒多;查看代码,事务没有设置超时时间,默认不超时或根据数据库默认设置,经后期测试为是不超时;当事务超过接口超时时间后,接口直接返回超时失败,但是事务并没有结束,而是等待竞争锁资源,获取到锁后继续执行,并且入库成功;从而赵成接口返回失败,实际入库成功的不一致现象;
解决办法:设置超时时间
1.spring的声明式事务:
@Transactional(rollbackFor = Exception.class, timeout = 3)
2.编程式事务
//开启事务 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // 事物隔离级别,开启新事务 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事务超时时间(秒) def.setTimeout(3); // 获得事务状态 TransactionStatus status = transactionManager.getTransaction(def); try { ... //提交事务 transactionManager.commit(status); log.info("成功"); } catch (TransactionTimedOutException e){ transactionManager.rollback(status); log.error("超时异常:", e); } catch (Exception e) { transactionManager.rollback(status); log.error("异常:", e); }
好记性不如烂笔头!