java - Spring @Transaction 和 @Async 用于数据库操作
问题描述
在 Spring 应用程序中,当我们收到消息时,@Service 持久 bean 正在调用数据库操作以插入数据库和并行 @Service 以解析和处理消息。在这种情况下,persist 使用@Transactional。为了使流程并行,是否建议添加@Async for persist。
此外,persist 服务调用的每个保存方法都有@Aspect,用于日志记录和审计。
- @Async 是否可用于数据库操作?
- @Async 是否创建表锁?
解决方案
@Async 所做的只是导致被注释组件的方法在另一个线程上执行,它从池中获取线程(可以指定,因此您可以为某些操作选择具有专用池)。
@Async 本身不做任何事情来锁定数据库表或任何其他与数据库相关的事情。如果您想要数据库级锁定,则必须通过其他方式实现。如果您希望调用使用事务,则必须在被异步调用的组件上使用 @Transactional 注释。该事务将与调用者的事务分开。当然,根据隔离级别和数据库实现,事务可能会导致数据库锁定。
将@Async 用于数据库工作很棘手。跨线程传递的 jpa 持久实体发生了一个陷阱,当它们具有在新线程中实现的惰性属性时(代理现在无效,因为它无法从旧线程到达 entityManager)。如果线程之间传递的东西是不可变的,那就更安全了。
@Async 增加了复杂性并且很难推理。存在竞争条件和死锁的机会,如果您没有完全正确地解决问题,那么可能会发生坏事,并且您不能指望通过测试来发现问题。它在没有网络的情况下工作,如果您想要任何基础设施来帮助处理异常、重试或其他恢复,您必须自己提供。
所以不,我不一定认为它是可取的。在您的工具箱中拥有它是一项很好的功能,它可能对一些孤立的案例有所帮助,但普遍使用似乎是一件坏事。如果您正在寻找在不阻塞的情况下持久保存数据的方法,还有其他选择。
推荐阅读
- google-analytics - 在 Google Analytics 中,如何为虚拟页面浏览量计算平均页面负载
- java - 回收器添加侦听器 onScrollStateChanged 回调滚动状态“SCROLL_STATE_IDLE”,延迟时间不可忽略
- laravel - 在一台服务器上运行两个 Laravel Echo Server (Socket.io) 实例?
- sql - 节点不工作
- powerbi - 以 hh:mm:ss 为单位的 PowerBi 持续时间计算
- c++ - Cython:共享对象中的未定义符号
- r - 在我的函数包 R 中修复编码 UTF-8 的最佳方法
- node.js - 我在 node.js rest api 创建中的 request.body 未定义
- python - 删除重复的 seq 名称 pandas
- python - Django - 渲染一个存储在数据库字段中的变量