我从最近几个月开始使用Spring框架。我有一个关于事务管理器如何在以下场景中工作的问题。
场景:我正在进行一个Spring批处理,其中ItemReader多次调用下面的方法。此方法从“STUDENTS”表中获取状态为“NOT COMPLETED”的记录列表,并将这些记录的状态更新为“IN PROGRESS”。我正在处理1000万条记录,因此我计划使用多个线程和多个JVM来执行我的批处理。
解决方案到目前为止已实现:我已使此方法同步,以确保在给定时间只有单个线程获取记录,因此没有两个线程将尝试获取相同的“NOT COMPLETED”记录。还添加了@Transactional,以便在此方法中出现任何问题时,spring将回滚更改。
问题:事务管理如何使用多个JVM访问一个数据库?如果我正在运行我的应用程序的2-3个实例,那么如何确保这些实例不会尝试获取状态为“未完成”的相同记录?春天有这个功能吗?
@Transactional
public synchronized List<Student> processStudentRecords(){
List<Student> students = getNotCompletedRecords();
if(null != students && students.size() > 0){
updateStatusToInProgress(students);
}
return student;
}
要具体解决您的问题:
@Transactional
。 Spring Batch管理事务,并且该注释的使用将导致问题。但是,上述内容并未解决多个JVM的问题。我假设您在跨多个JVM的处理中使用某种远程分区。如果是这种情况,您的更新查询将类似于UPDATE STUDENTS SET FLAG = 'NOT COMPLETE' WHERE ID > ? AND FLAG IS NULL LIMIT 100
,其中ID是分区范围的起点,100是您的块大小。
标记行后,ItemReader
可以通过SELECT * FROM STUDENT WHERE ID > ? AND FLAG = 'NOT COMPLETE'
查询,其中ID是分区范围的开头。
上述技术允许您扩展到多个JVM,同时保留可重启性等内容。