【问题标题】:How to lock on select and release lock after update is committed using spring?使用spring提交更新后如何锁定选择和释放锁定?
【发布时间】:2019-02-27 15:22:46
【问题描述】:

我从过去几个月开始使用 spring,我有一个关于交易的问题。我的 spring 批处理作业中有一个 java 方法,它首先执行选择操作以获取状态为“未完成”的前 100 行,并对所选行进行更新以将状态更改为“进行中”。由于我正在处理大约 1000 万条记录,因此我想运行我的批处理作业的多个实例,并且每个实例都有多个线程。对于单个实例,为了确保两个线程没有获取同一组记录,我将我的方法设置为同步。但是,如果我运行批处理作业的多个实例(多个 JVM),即使我使用“乐观”或“悲观锁”或“选择更新”,这两个实例也很可能会获取同一组记录,因为我们无法在选择期间锁定记录。下面是显示的示例。事务 1 获取了 100 条记录,同时事务 2 也获取了 100 条记录,但是如果我启用锁定事务 2 等到事务 1 更新并提交。但是事务 2 再次执行相同的更新。

春天有什么办法让事务2的选择操作等到事务1的选择完成?

Transaction1        Transaction2
fetch 100 records   
                    fetch 100 records
update 100 records



 commit         
                    update 100 records
                    commit



@Transactional
public synchronized List<Student> processStudentRecords(){
List<Student> students = getNotCompletedRecords();
if(null != students && students.size() > 0){
    updateStatusToInProgress(students);
}
return student;
}

注意:我不能先更新再选择。如果建议任何替代方法,我将不胜感激?

【问题讨论】:

  • 您是不是碰巧从应用程序本身解决了这个问题?自您发布问题一年以来,我仍然无法从春天找到实现这一目标的答案。

标签: spring spring-batch spring-transactions optimistic-locking pessimistic-locking


【解决方案1】:

事务同步应该留给数据库服务器,而不是在应用程序级别进行管理。从数据库服务器的角度来看,无论您拥有多少个 JVM(线程),这些都是并发数据库客户端请求读/写操作。你不应该为这些担忧而烦恼。

您应该做的是在解决方案设计中尽量减少争用,例如,使用(remote) partitioning technique

如果我运行批处理作业的多个实例(多个 JVM),即使我使用“乐观”或“悲观锁”或“选择更新”,这两个实例也很可能会获取相同的记录集" 因为我们无法在选择期间锁定记录

分区数据将按设计消除所有这些问题。如果您为每个实例提供一组数据来处理,那么一个工作人员就不可能选择另一个工作人员的相同记录。迈克尔在这个答案中给出了一个详细的例子:https://stackoverflow.com/a/54889092/5019386

(逻辑)分区将解决争用问题,因为所有工作人员都会从/向同一个表读取/写入,但这就是您要解决的问题的本质。我的意思是你不需要在你的设计中开始锁定/解锁表,把它留给数据库。一些数据库服务器(如 Oracle)可以将同一张表的数据写入磁盘上的不同分区以优化并发访问(如果您使用分区可能会有所帮助),但这也是 Oracle 的业务,而不是 Spring(或任何其他框架)的业务。

不是每个人都能买得起 Oracle,所以我会在概念层面寻找解决方案。我已成功使用以下解决方案(“伪”物理分区)来解决与您类似的问题:

  • 第 1 步(串行):将未处理的数据复制/分区到临时表(串行)
  • 第 2 步(并行):在这些表上运行多个工作器,而不是在具有数百万行的源表上运行。
  • 第 3 步(串行):将处理后的数据复制/更新回原始表

第 2 步消除了争用问题。通常,与步骤 2 相比,(步骤 1 + 步骤 3)的成本可以忽略不计(如果步骤 2 连续完成,则更可忽略不计)。如果处理是瓶颈,这很有效。

希望这会有所帮助。

【讨论】:

  • 感谢@Mahmouc 的建议。我已经考虑过远程分区技术。仍然通过批处理作业需要 1 个小时,有 15 个线程,而我的 CPU 利用率为 100%。我非常感谢您对数据分区的建议,但这不是我现在正在寻找的。我打算使用数据库锁定机制
猜你喜欢
  • 2013-03-22
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2011-01-22
相关资源
最近更新 更多