我正在使用弹簧批。我有超过 10 个批处理进程运行相同的数据库连接。我已经使用春季调度运行了这些批次。但它显示以下错误:
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]; SQL state [72000]; error code [8177]; ORA-08177: can't serialize access for this transaction
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1539)
........
Caused by: java.sql.SQLException: ORA-08177: can't serialize access for this transaction
.....
Caused by: Error : 8177, Position : 0, Sql = INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (:1 , :2 , :3 , :4 ), OriginalSql = INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?), Error Msg = ORA-08177: can't serialize access for this transaction
at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:636)
... 53 more
我在下面配置了 Spring 批处理,如下所示:
应用程序属性:
spring.datasource.url=myurl
spring.datasource.username=mydbName
spring.datasource.password=myPassword
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.batch.job.enabled=true
spring.batch.job.chunk.size=10
# 0 */2 * * * ? --> 2 minutes
batch-schduled-time=0 */2 * * * ?
我的批处理作业
@Component
@RequiredArgsConstructor
@Slf4j
public class MyJob {
private final MyTrxSummaryRepo approvedTrxSummaryRepo;
private final MyApprovedTransactionRepo corpApprovedTransactionRepo;
private final MyTransactionViewRepo allApprovedTransactionViewRepo;
private final ProcessorStep1 batchProcessorStep1;
private final WriterStep1 batchWriterStep1;
private final PlatformTransactionManager transactionManager;
private final JobRepository jobRepository;
@Value("${spring.batch.job.chunk.size}")
private Integer chunkSize;
public Job createEft(){
String id = UUID.randomUUID().toString();
return new JobBuilder(id, jobRepository)
.incrementer(new RunIdIncrementer())
.start(step1())
.build();
}
private Step step1(){
return new StepBuilder("step1", jobRepository)
.<MyTrxSummery,MyTrxSummery> chunk(chunkSize, transactionManager)
.reader(new ReaderStep1(approvedTrxSummaryRepo,corpApprovedTransactionRepo))
.processor(batchProcessorStep1)
.writer(batchWriterStep1)
.build();
}
}
BatchBean
@Configuration
public class BatchBean {
@Bean
public ProcessorStep1 batchProcessorStep1() {
return new ProcessorStep1();
}
@Bean
public WriterStep1 batchWriterStep1() {
return new WriterStep1();
}
}
MyTrxSummery 实体和存储库:
@Entity
@Table(name = "mySummeryTb")
@Data
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MyTrxSummery {
@Id
@Column(name = "TRANSACTION_REFERENCE")
private String transactionReference;
.........
}
@Repository
public interface MyTrxSummaryRepo extends JpaRepository<MyTrxSummery, Long> {
@Query("myquery.....")
List<MyTrxSummery> getAllTransaction();
MyTrxSummery findByTransactionReference(String transactionReference);
@Modifying
@Query(" update.....")
public void updateApprovedTrxSummeriesByTransactionReference(String transactionReference);
@Modifying
@Query(" update......")
public void updateSegmentedTransaction(String transactionReference);
}
MyTransaction 实体和存储库::
@Entity
@Table(name = "CORP_APPROVED_TRANSACTION")
@Data
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class CorpApprovedTransaction {
@Id
@Column(name = "TRANSACTION_ID")
private Long transactionId;
............
}
@Transactional
@Repository
public interface MyTransactionRepo extends JpaRepository<MyTransaction, Long> {
@Query("select....")
List<MyTransaction> findSegmentedTransaction(String transactionReference);
@Modifying
@Query("update ..")
public void updateMyTransactionByTransactionReference(String transactionReference);
}
读取器步骤1、处理器步骤1和写入器步骤1
@Slf4j
public class ReaderStep1 implements ItemReader<MyTrxSummery> {
private Iterator<MyTrxSummery> iterator;
public ReaderStep1(MyTrxSummaryRepo myTrxSummaryRepo, MyTransactionRepo corpApprovedTransactionRepo) {
List<MyTrxSummery> list = myTrxSummaryRepo.getAllTransaction();
if(!list.isEmpty()){
this.iterator = list.iterator();
}
}
@Override
public MyTrxSummery read() {
return (iterator != null && iterator.hasNext()) ? iterator.next() : null;
}
}
@Slf4j
public class ProcessorStep1 implements ItemProcessor<MyTrxSummery, MyTrxSummery> {
@Autowired
private MyTrxSummaryRepo approvedTrxSummaryRepo;
@Autowired
private MyTransactionRepo corpApprovedTransactionRepo;
@Override
public MyTrxSummery process(MyTrxSummery item) throws Exception {
......
}
}
@Slf4j
public class WriterStep1 implements ItemWriter<MyTrxSummery> {
@Override
public void write(Chunk<? extends MyTrxSummery> chunk) {
........
}
}
ScheduledJobBean
@Component
@Slf4j
public class ScheduledJobBean {
@Autowired
JobLauncher jobLauncher;
@Autowired
MyJob eftJob;
@Scheduled(cron = "${batch-schduled-time}")
public void perform() throws Exception
{
try {
JobExecution execution = jobLauncher.run(eftJob.createEft(), new JobParameters());
}catch (Exception ex) {
ex.printStackTrace();
}
}
}
我的代码有什么问题...
请帮我解决问题......
在 ORACLE 支持网站上找到:
“使用可序列化事务并发插入到带有索引的表中 可能会导致事务尝试重新读取的索引拆分并导致错误 ORA-08177
修复: 插入较少数量的行(例如更频繁地提交)
-或-
捕获应用程序中的错误代码并重试操作
-或-
这可以通过在正常表创建期间实现“行依赖关系”来解决。”