尝试同时启动两个或多个 Spring Batch 作业时,会抛出错误:ORA-08177: 无法序列化此事务的访问
php小编西瓜在使用Spring Batch时,可能会遇到一个问题:当尝试同时启动两个或多个Spring Batch作业时,会抛出错误:ORA-08177: 无法序列化此事务的访问。这个错误可能让人困惑,但实际上它是由于数据库锁定问题导致的。在解决这个问题之前,我们需要了解一些关于Spring Batch和数据库事务的背景知识。
问题内容
尝试使用 completablefuture 并行运行两个 spring batch 作业时遇到错误。错误信息如下:
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
我正在使用 spring batch 5.x、spring boot 3.1.6、jdk 17
应用程序属性
spring.batch.repository.isolationlevelforcreate=isolation_read_committed spring.batch.isolationlevel=read_committed spring.batch.jdbc.table-prefix=batch_ spring.batch.job.enabled=false
batchconfig.java
@configuration public class batchconfig { @bean("simpletaskexecutor") public taskexecutor simpletaskexecutor() { simpleasynctaskexecutor asynctaskexecutor = new simpleasynctaskexecutor("simpletaskexecutor"); asynctaskexecutor.setconcurrencylimit(concurrencycount); return asynctaskexecutor; } @bean("joblauncherasync") @scope("prototype") public joblauncher joblauncherasync(datasource datasource, jobrepository jobrepository) throws exception { taskexecutorjoblauncher joblauncher = new taskexecutorjoblauncher(); joblauncher.setjobrepository(jobrepository); joblauncher.settaskexecutor(simpletaskexecutor()); joblauncher.afterpropertiesset(); return joblauncher; } @bean public jpatransactionmanager transactionmanager(entitymanagerfactory entitymanagerfactory) { return new jpatransactionmanager(entitymanagerfactory); } @bean public batchjobexecutionlistener batchjobexecutionlistener() { return new batchjobexecutionlistener(); } @bean public batchjobstepexecutionlistner batchjobstepexecutionlistner() { return new batchjobstepexecutionlistner(); }
}
employeejobconfig.java
@configuration @import(batchconfig.class) public class employeejobconfig{ @autowired employeestatuswritter employeestatuswritter; @autowired employeependingprocessor employeependingprocessor; @bean("employeependingreader") public jpapagingitemreader<employee> employeependingreader(datasource ds,entitymanagerfactory entitymanagerfactory) { jpapagingitemreader<employee> jpareader = new jpapagingitemreader<>(); jpareader.setentitymanagerfactory(entitymanagerfactory); jpareader.setquerystring("select e from employee e"); jpareader.setpagesize(5000); return jpareader; } @bean("employeespinvokestep") public step employeespinvokestep(@qualifier("employeependingreader") itemreader<employee> reader, @qualifier("employeestatuswritter") itemwriter<employee> writer, @qualifier("employeependingprocessor") itemprocessor<employee, employee> processor,jobrepository jobrepository, platformtransactionmanager transactionmanager,batchjobstepexecutionlistner batchjobstepexecutionlistner,taskexecutor simpletaskexecutor) { return new stepbuilder("employeespinvokestep",jobrepository) .<employee, employee>chunk(50,transactionmanager).reader(reader) .processor(processor).writer(writer) .listener(batchjobstepexecutionlistner) .taskexecutor(simpletaskexecutor) .build(); } @bean("employeespjob") public job employeespjob(@qualifier("employeespinvokestep") step employeespinvokestep,jobrepository jobrepository,batchjobexecutionlistener batchjobexecutionlistener) { return new jobbuilder("employeespjob",jobrepository) .incrementer(new runidincrementer()) .listener(batchjobexecutionlistener) .start(employeespinvokestep) .build(); } }
managerconfig.java
@configuration @import(batchconfig.class) public class managerconfig { @autowired managerstatuswritter managerstatuswritter; @autowired managerpendingprocessor managerpendingprocessor; @bean("managerpendingreader") public jpapagingitemreader<manager> managerpendingreader(datasource ds,entitymanagerfactory entitymanagerfactory) { jpapagingitemreader<manager> jpareader = new jpapagingitemreader<>(); jpareader.setentitymanagerfactory(entitymanagerfactory); jpareader.setquerystring("select m from manager m"); jpareader.setpagesize(5000); return jpareader; } @bean("managerspinvokestep") public step indvinvoiceconsctlspinvokestep(@qualifier("managerpendingreader") itemreader<manager> reader, @qualifier("managerstatuswritter") itemwriter<manager> writer, @qualifier("managerpendingprocessor") itemprocessor<manager, manager> processor,jobrepository jobrepository, platformtransactionmanager transactionmanager,batchjobstepexecutionlistner batchjobstepexecutionlistner,taskexecutor simpletaskexecutor) { return new stepbuilder("managerspinvokestep",jobrepository) .<manager, manager>chunk(5000,transactionmanager).reader(reader) .processor(processor).writer(writer) .listener(batchjobstepexecutionlistner) .taskexecutor(simpletaskexecutor) .build(); } @bean("managerspjob") public job managerspjob(@qualifier("managerspinvokestep") step indvinvoiceconsctlspinvokestep,jobrepository jobrepository,batchjobexecutionlistener batchjobexecutionlistener) { return new jobbuilder("managerspjob",jobrepository) .incrementer(new runidincrementer()) .listener(batchjobexecutionlistener) .start(indvinvoiceconsctlspinvokestep) .build(); } }
batchjobmanager.java
@service public class batchjobmanager { @autowired applicationcontext context; @autowired batchexecutorservice batchexecutorservice; @autowired batchjobrunner batchjobrunner; public void startjob() { try { system.out.println("batchjobmanager called .. "+new date()); string[] invoicenames={"employeespjob","managerspjob"}; list<string> invoicenameslist = arrays.aslist(invoicenames); launchasyn(getbatchjoblist(invoicenameslist)); } catch (exception e) { system.out.println("while loading job.."); e.printstacktrace(); } } public list<batchjob> getbatchjoblist(list<string> jobnames) throws exception{ list<batchjob> batchjoblist=new arraylist<batchjob>(); for(string job:jobnames) { batchjob batchjob= batchjob.builder().jobname(invoicejob).build(); batchjoblist.add(batchjob); } return batchjoblist; } public void launchasyn( list<batchjob> batchjoblist) throws exception{ list<completablefuture<batchjob>> batchjobfuturelist = new arraylist<completablefuture<batchjob>>(); for(batchjob batchjob:batchjoblist) { completablefuture<batchjob> jobfuture = batchexecutorservice.execute(batchjob, asynctaskexecutor); batchjobfuturelist.add(jobfuture); } completablefuture<void> jobfutureresult = completablefuture .allof(batchjobfuturelist.toarray(new completablefuture[batchjobfuturelist.size()])); completablefuture<list<canbatchjob>> allcompletablefuture = jobfutureresult.thenapply(future -> { return batchjobfuturelist.stream().map(completablefuture -> completablefuture.join()) .collect(collectors.tolist()); }); list<batchjob> resultfuturelist=allcompletablefuture.get(); for(batchjob batch:resultfuturelist) { system.out.println("status "+batch.getiscompleted()); } } }
batchexecutorservice.java
@service public class batchexecutorservice { @autowired batchjobrunner batchjobrunner; public completablefuture<canbatchjob> execute(canbatchjob canbatchjob,taskexecutor threadpooltaskexecutor){ return completablefuture.supplyasync(() -> batchjobrunner.execute(canbatchjob),threadpooltaskexecutor); } }
batchjobrunner.java
@service public class batchjobrunner { @autowired applicationcontext context; @autowired @qualifier("joblauncherasync") joblauncher joblauncherasync; /* * @autowired joblauncher joblauncherasync; */ public batchjob execute(batchjob batchjob) { try { system.out.println(" batchjob"+batchjob.getjobname()+" called ..."); joblauncherasync.run(getjob(batchjob.getjobname()), getjobparameters(batchjob.getjobname())); thread.sleep(15000); batchjob.setiscompleted(true); system.out.println(" batchjob"+batchjob.getjobname()+" completed ..."); } catch(exception e) { system.out.println("exception "+e.getmessage()); batchjob.seterrordesc(e.getmessage().tostring()); e.printstacktrace(); } return canbatchjob; } public job getjob(string jobname) { return (job) context.getbean(jobname); } public jobparameters getjobparameters(string jobname) { jobparameters jobparameters = new jobparametersbuilder() .addstring("unique_id", uuid.randomuuid().tostring(), true) .addstring("job_name", jobname, true) .adddate("execution_start_date", date.from(instant.now()), true).tojobparameters(); return jobparameters; } }
batchjob.java
public class BatchJob { private String jobName; private Boolean isCompleted; private String errorDesc; }
作业在逐一或按顺序执行时成功运行。但是,在使用 completablefuture 时,遇到了问题。同时启动 spring 批处理作业是正确的方法吗?
解决方法
1.将以下属性添加到application.properties
spring.main.allow-bean-definition-overriding=true
2.更新了 joblauncher(),如下 batchconfig.java 中所示
@bean("joblauncher") public joblauncher joblauncher(datasource datasource, jobrepository jobrepository) throws exception { taskexecutorjoblauncher joblauncher = new taskexecutorjoblauncher(); joblauncher.setjobrepository(jobrepository); joblauncher.settaskexecutor(simpletaskexecutor()); joblauncher.afterpropertiesset(); return joblauncher; }
删除了 completablefuture。
删除了 batchexecutorservice.java
在 batchjobmanager.java 中添加了以下方法来调用作业。
public void launchSync(List<BatchJob> batchJobList) throws Exception { for(BatchJob batchJob:batchJobList) { batchJobRunner.execute(batchJob); } }
登录后复制以上是尝试同时启动两个或多个 Spring Batch 作业时,会抛出错误:ORA-08177: 无法序列化此事务的访问的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

RedmiNote13RPro是一款性能配置非常不错的全新机型,这款手机中有一个隐藏相册的功能十分好用,它可以帮助用户将相册隐藏起来,让别人无法查看你的相册。接下来,小编就来给大家说一说红米Note13RPro怎么隐藏相册,帮助大家保护隐私。红米Note13RPro怎么隐藏相册?1、进入小米手机的设置里。2、然后再点击隐私和保护。3、在这里再点击保护隐私。4、点击保险箱。5、最后在这里就可以设置私密相册。常见问题连接蓝牙换输入法主题更换出厂设置隐藏应用投屏电视NFC开启双卡安装激活时间

不要改变原内容的意思,微调内容,重写内容,不要续写红米Note13RPro不仅性能出色,使用体验更加出色,为了让大家有更舒适的使用体验,红米Note13RPro配备了字体调整功能,让用户能够调整自己的手机的字体。如果你想知道红米Note13RPro怎么调整字体大小,那么就来看一看吧。红米Note13RPro怎么调整字体大小?1.打开“设置”应用程序。2.滚动到底部,选择“显示”。3.点击“文字大小”。4.在此屏幕上,您可以通过拖动滑块调整字体大小或者选择预设字体大小。5.调整完毕后,按“确定”保

红米Note13RPro的拍照功能非常好用,特别是在拍照的时候会模拟相机快门的声音,不过这个功能在图书馆等一些安静的场合会影响别人,所以很多用户想知道红米Note13RPro怎么关闭拍照声音,下面就让小编来告诉你。红米Note13RPro怎么关闭拍照声音?1.第一种方法,首先需要打开手机的设置。2.然后在设置菜单下找到系统应用。3.紧接着我们在系统应用界面下找到相机选项。4.最后,我们在相机界面下就可以设置相机声音的关闭与否了,只需要将相机声音右边的开关关闭就可以了。5.第二种方法,第一步,打开

红米Note13RPro手机在软件功能上集成了多项智能工具,其中,从图片中快速准确地提取文字内容便是其中之一,下面小编将为大家介绍红米Note13RPro如何提取图片中的文字。红米Note13RPro怎么提取图中的文字?使用小米扫码功能,打开手机的扫码应用,点击图片图标,选择一张图片,然后点击右边的“识别文字”选项,成功提取出图片中的文字。通过手机相册操作。在手机相册中找到需要提取文字的图片,点击图片下方的“更多”,选择“提取文字”,识别成功后,可以根据需要复制或保存文本。利用微信小程序。打开微

RedmiNote13RPro这款手机最近是非常火爆的,很多消费者都购买了这款手机,不过很多用户是第一次使用这款手机所以不清楚红米Note13RPro怎么连接电脑,对此,小编在这里为大家带来了详细的教程介绍。红米Note13RPro怎么连接电脑?1.使用USB数据线将红米手机连接到电脑的USB接口上。2.打开手机设置,击选项,将USB调试打开。3.在电脑上打开设备管理器,找到移动设备选项。4.右键点击移动设备,选择更新驱动程序,然后选择自动搜索更新的驱动程序。5.如果电脑没有自动搜索到驱动程序,

整个活吧是一款非常好玩的休闲解谜小游戏,大家可以在多平台体验!游戏提供了无数精彩的关卡等待解锁,每个关卡都充满了新奇和挑战,让你体验回答问题的有趣冒险,开启全新的游戏内容。那么整个活吧全关卡怎么通关呢?今天给大家带来了《整个活吧》全关卡通关攻略大全分享,大家过关遇到问题可以来参考一下哦!《整个活吧》全关卡通关攻略大全《整个活吧》全关卡通关攻略大全帮她守岁人鬼情未了帮小姐姐识别渣男狼外婆帮小女孩脱离危险户外探险假装看不见阿飘变回人形帮猩猩修成人形后座有人保持镇定和女鬼周旋夜班出租车保持镇定和女鬼周

RedmiNote13RPro是一款备受广大用户喜爱的手机。这款手机提供了特别的方法来让流量显示在手机上,如果你还不知道RedmiNote13RPro怎么设置显示流量,那么就跟随小编一起来了解一下吧。红米Note13RPro怎么设置流量显示?1、进入“设置”,点击“双卡移动网络”。2、下滑选择“流量套餐设置”选项。3、开启“通知栏显示流量信息”和“状态栏显示当时网速”右侧的功能开关。4、设置成功后,下拉状态栏就可以看到实时网速及流量信息的显示了。常见问题连接蓝牙换输入法主题更换出厂设置隐藏应用投

整个活吧是抖音上非常火爆的趣味闯关小游戏,游戏中有超多的关卡等大家挑战!游戏中关卡西游美人这一关中大家需要帮西游女角色归位,具体怎么过关呢?下面是小编给大家带来的《整个活吧》西游美人帮西游女角色归位通关攻略,不清楚如何过关的小伙伴们一起来看看吧,希望能帮到大家。《整个活吧》西游美人帮西游女角色归位通关攻略西游美人帮西游女角色归位1、点击卷轴出现女角色2、白骨精、孔雀精需要点击切换动作3、答案如下图所示:《整个活吧》全关卡通关攻略大全帮她守岁人鬼情未了帮小姐姐识别渣男狼外婆帮小女孩脱离危险户外探险