BAT华为大佬教你大厂如何保证数据库事务生效就能正确回滚?

BAT华为大佬教你大厂如何保证数据库事务生效就能正确回滚?
最新回答
深蓝菇凉

2026-05-13 11:50:50

大厂保证数据库事务生效且在异常时正确回滚,主要通过合理配置事务注解、正确处理异常以及利用日志验证实现,具体如下:

事务生效与回滚条件
  • 事务生效基础:使用@Transactional注解标记方法,Spring会基于AOP实现事务管理,通过try-catch包裹被注解方法,根据异常情况决定事务提交或回滚。
  • 事务回滚条件:

    异常传播:只有异常传播出标记@Transactional注解的方法,事务才会回滚。在Spring的TransactionAspectSupport的invokeWithinTransaction方法中,捕获到异常才会进行后续事务处理。

    异常类型:默认情况下,出现RuntimeException(非受检异常)或Error时,Spring会回滚事务。受检异常一般是业务异常或类似另一种方法的返回值,出现这类异常可能业务还能完成,所以不会主动回滚;而Error或RuntimeException代表非预期结果,应回滚。

异常处理不当导致事务不回滚的情况
  • 捕获所有异常:例如createUserError1方法,虽然会抛出RuntimeException,但方法内捕获了所有异常,导致异常无法传播出去,事务不会回滚。

  • 传播受检异常:如createUserError2方法,注册用户同时有一次otherTask文件读操作,若读文件失败,希望用户注册的DB操作回滚。但该方法虽无捕获异常,因otherTask抛受检异常,传播出去的也是受检异常,事务同样不回滚。
修复方法
  • 手动设置事务回滚:如果希望自己捕获异常并处理,可手动设置让当前事务处于回滚态。示例代码如下:
@Transactional public void createUserRight1(String name) { try { userRepository.save(new UserEntity(name)); throw new RuntimeException("error"); } catch (Exception ex) { log.error("create user failed", ex); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } }

查看日志,若出现Transactional code has requested rollback,则表示手动请求回滚成功。

  • 配置注解属性:在注解中声明,期望遇到所有的Exception都回滚事务,以突破默认不回滚受检异常的限制。示例代码如下:
@Transactional(rollbackFor = Exception.class) public void createUserRight2(String name) throws IOException { userRepository.save(new UserEntity(name)); readFile(); }

查看日志,若提示回滚,则表示配置成功。

总结与注意事项
  • 异常处理:由于异常处理不正确,会导致虽然事务生效,但出现异常时没回滚。Spring默认只对被@Transactional注解的方法出现RuntimeException和Error时回滚,若方法捕获了异常,就需要通过手写代码处理事务回滚。
  • 注解配置:若希望Spring针对其他异常也可回滚,可相应配置@Transactional注解的rollbackFor和noRollbackFor属性覆盖Spring的默认配置。
  • 事务传播:有些业务可能包含多次DB操作,不一定希望将两次操作作为一个事务,这时就需仔细考虑事务传播的配置。