Mysql spring/jpa/hibernate中乐观锁的简单设计问题

Mysql spring/jpa/hibernate中乐观锁的简单设计问题,mysql,hibernate,spring,jpa,optimistic-locking,Mysql,Hibernate,Spring,Jpa,Optimistic Locking,我有一个对象GeneralKnowledgetTest,它包含很多统计字段(RatingScont、ResponseCount、ratingStars…),每次用户进行测试时都会更新这些字段(takeTest()->transactional method) 可能会有很多用户同时进行相同的测试,因此我考虑实现乐观锁(@version)和一个拦截器,在抛出乐观锁异常时重试takeTest方法 因此,在takeTest方法中,我总是获得一个新的GeneralKnowledgeTest实例,例如ent

我有一个对象GeneralKnowledgetTest,它包含很多统计字段(RatingScont、ResponseCount、ratingStars…),每次用户进行测试时都会更新这些字段(takeTest()->transactional method)

可能会有很多用户同时进行相同的测试,因此我考虑实现乐观锁(@version)和一个拦截器,在抛出乐观锁异常时重试takeTest方法

因此,在takeTest方法中,我总是获得一个新的GeneralKnowledgeTest实例,例如entityManager.find(testId),然后更新其统计字段。如果抛出乐观异常,拦截器将简单地重试takeTest方法,直到成功

你对这个程序有什么看法。对于可能有很多用户尝试进行相同测试的系统,这是实现乐观锁定的好方法吗


另外,如果抛出乐观锁异常,业务部门不会允许显示任何警告消息,因此必须使用拦截器才能顺利执行…

我假设这些统计信息仅在测试结束时更新,并且测试需要合理的运行时间,因此,这将降低am乐观锁失败的可能性。此外,用户是否有可能因为在设定的时间开始测试而突然完成测试?这将增加锁失败的可能性


如果吞吐量使得并发更新仍然存在,那么最好在内存中聚合统计数据(以线程安全的方式),并定期将它们写入数据库。

这听起来是一种有效的方法:

Hibernate在刷新时检查实例版本,如果检测到并发修改,则引发异常。由开发人员捕获并处理此异常。常见选项是用户有机会合并更改或使用非陈旧数据重新启动业务对话

您还可以查看将IsolationLevel设置为序列化或锁定表行


另一个选项可能是分离对象,使用输入的统计信息更新对象,并使用调度程序等重新附加(更新)对象。然而,这可能需要同步您的服务方法(updatestats),因为此服务可能是代理的,所以我认为同步是不可能的

很可能很多用户都可以在同一时间完成测试(比如当天的测试等等…)。我已经读到乐观锁在性能方面是可以的,所以没有数据库锁。(假设100个用户在同一时间完成同一个测试,也认为TaKestST是一个复杂的方法,它创建了许多额外的DB对象,使得事务需要更长的时间)。但总的来说,我所建议的方法有什么问题吗?是否存在任何错误或缺陷?提前谢谢你,没有错误。乐观锁定失败将导致重新读取数据,这将增加数据库负载,重新执行take test逻辑将增加CPU负载。这种方法没有错,只是取决于您期望锁失败的频率。