如果开发者没有注意到一个方法是被事务嵌套的,那么就<br>可能会再方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作
这些操作自身是无法回滚的,这就会导致数据的不一致。<br>可能RPC调用成功了,但是本地事务回滚了,可是PRC调用无法回滚了。
在事务中有远程调用,就会拉长整个事务。那么久会导致本事务的数据库<br>连接一直被占用,那么如果类似操作过多,就会导致数据库连接池耗尽。
声明式事务用不对容易失效
@Transactional 应用在非 public,final修饰的方法上
@Transactional 注解属性 propagation 设置错误
@Transactional 注解属性 rollbackFor 设置错误
同一个类中方法调用,导致@Transactional失效
错误例子
@Service<br>public class UserService {<br><br> @Autowired<br> private UserMapper userMapper;<br><br> <br> public void add(UserModel userModel) {<br> userMapper.insertUser(userModel);<br> updateStatus(userModel);<br> }<br><br> @Transactional<br> public void updateStatus(UserModel userModel) {<br> doSameThing();<br> }<br>}
解决1:只需要新加一个Service方法,把@Transactional注解加到新Service方法上
解决2:Service类中注入自己
解决3:
@Servcie<br>public class ServiceA {<br><br> public void save(User user) {<br> queryData1();<br> queryData2();<br> ((ServiceA)AopContext.currentProxy()).doSave(user);<br> }<br><br> @Transactional(rollbackFor=Exception.class)<br> public void doSave(User user) {<br> addData1();<br> updateData2();<br> }<br> }
异常被catch捕获导致@Transactional失效
因为spring事务,默认情况下只会回滚RuntimeException(运行时异常)和Error(错误),<br>对于普通的Exception(非运行时异常),它不会回滚。
数据库引擎不支持事务
(类本身) 未被spring管理
多线程调用
@Slf4j<br>@Service<br>public class UserService {<br><br> @Autowired<br> private UserMapper userMapper;<br> @Autowired<br> private RoleService roleService;<br><br> @Transactional<br> public void add(UserModel userModel) throws Exception {<br> userMapper.insertUser(userModel);<br> new Thread(() -> {<br> roleService.doOtherThing();<br> }).start();<br> }<br>}<br><br>@Service<br>public class RoleService {<br><br> @Transactional<br> public void doOtherThing() {<br> System.out.println("保存role表数据");<br> }<br>}