无法在春季批处理中序列化此事务的访问
Posted
技术标签:
【中文标题】无法在春季批处理中序列化此事务的访问【英文标题】:can't serialize access for this transaction in spring batch 【发布时间】:2019-02-02 10:11:27 【问题描述】:我正在使用 Spring Batch 和 Spring Boot 来处理我的 Csv 文件。当我运行应用程序时,我得到了错误跟踪。
2018-08-27 16:23:35.694 INFO 12016 --- [nio-9004-exec-1] o.s.b.c.r.s.JobRepositoryFactoryBean : No database type set, using meta data indicating: ORACLE
2018-08-27 16:23:36.025 INFO 12016 --- [nio-9004-exec-1] o.s.b.c.l.support.SimpleJobLauncher : No TaskExecutor has been set, defaulting to synchronous executor.
2018-08-27 16:23:36.898 INFO 12016 --- [nio-9004-exec-1] o.s.b.f.xml.XmlBeanDefinitionReader : Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2018-08-27 16:23:36.965 INFO 12016 --- [nio-9004-exec-1] o.s.jdbc.support.SQLErrorCodesFactory : SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, mysql, Oracle, PostgreSQL, Sybase]
2018-08-27 16:23:37.005 ERROR 12016 --- [nio-9004-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.CannotSerializeTransactionException: PreparedStatementCallback; SQL [INSERT INTO BATCH_JOB_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) VALUES(?, ?, ?)]; ORA-08177: can't serialize access for this transaction
; nested exception is java.sql.SQLException: ORA-08177: can't serialize access for this transaction
] with root cause
java.sql.SQLException: ORA-08177: can't serialize access for this transaction
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1017) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:655) ~[ojdbc7-12.1.0.1.jar!/:12.1.0.1.0]
at oracle.jdbc.driver.T4CTTI
在谷歌搜索后,我发现我们必须实例化 JobRepositoryFactoryBean。所以我在我的 BatchConfiguration 中做了同样的事情,如下所示。
@Autowired
private DataSource dataSource;
@Autowired
private DataSourceTransactionManager transactionManager;
@Bean
public JobRepositoryFactoryBean jobRepository() throws SQLException
JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
factoryBean.setDatabaseType("ORACLE");
factoryBean.setDataSource(dataSource);
factoryBean.setTransactionManager(transactionManager);
factoryBean.setIsolationLevelForCreate("ISOLATION_READ_UNCOMMITTED");
return factoryBean;
Datasource ** 和 **TransactionManager bean 在我的 DBConfiguration 中,如下所示。
@Bean
public DataSource dataSource() throws SQLException
OracleDataSource dataSource = new OracleDataSource();
dataSource.setUser("xxxxxx");
dataSource.setPassword("xxxxx");
dataSource.setURL("xxxxx");
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
@Bean(name="transactionManager")
public PlatformTransactionManager transactionManager() throws SQLException
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource());
return transactionManager;
然后我遇到错误
***************************
APPLICATION FAILED TO START
***************************
Description:
Field transactionManager in com.comcast.FileProcess.configuration.SprintgBatchConfiguration required a bean of type 'org.springframework.jdbc.datasource.DataSourceTransactionManager' that could not be found.
- Bean method 'transactionManager' in 'DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration' not loaded because @ConditionalOnMissingBean (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) found bean 'transactionManager'
Action:
Consider revisiting the conditions above or defining a bean of type 'org.springframework.jdbc.datasource.DataSourceTransactionManager' in your configuration.
谁能帮我解决这个问题并运行我的批处理。
【问题讨论】:
【参考方案1】:关于APPLICATION FAILED TO START
错误,你需要让你的事务管理器bean定义方法返回实际类型DataSourceTransactionManager
而不是PlatformTransactionManager
:
@Bean(name="transactionManager")
public DataSourceTransactionManager transactionManager() throws SQLException
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource());
return transactionManager;
关于java.sql.SQLException: ORA-08177: can't serialize access for this transaction
错误,看起来IsolationLevelForCreate
仍然是ISOLATION_SERIALIZABLE
,并且您的数据库无法序列化事务。这可能是由于您的工作存储库没有考虑在内。我会让jobRepository
方法返回作业存储库本身(如示例here)而不是工厂bean:
@Bean
public JobRepository jobRepository() throws SQLException
JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
factoryBean.setDatabaseType("ORACLE");
factoryBean.setDataSource(dataSource);
factoryBean.setTransactionManager(transactionManager);
factoryBean.setIsolationLevelForCreate("ISOLATION_READ_UNCOMMITTED");
return factoryBean.getObject();
这样,您的作业存储库将正确配置为ISOLATION_READ_UNCOMMITTED
,并且您的数据库不会尝试序列化事务。
【讨论】:
感谢您的时间和投入。我按照你的建议做了同样的事情,但在启动应用程序时仍然出现异常。 *************************** 应用程序无法启动 *********** ****************** com.comcast.FileProcess.configuration.SprintgBatchConfiguration 中的字段 transactionManager 需要找不到类型为“org.springframework.jdbc.datasource.DataSourceTransactionManager”的 bean。 - 'DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration' 中的 Bean 方法 'transactionManager' 未加载,因为 @ConditionalOnMissingBean(类型:org.springframework.transaction.PlatformTransactionManager;SearchStrategy: all)找到了 bean 'transactionManager' 行动:考虑重新审视上述条件或在您的配置中定义一个“org.springframework.jdbc.datasource.DataSourceTransactionManager”类型的bean。 你的DBConfiguration
是否正确放置在Spring Boot扫描的包中?看起来那里定义的 bean 不可见。所以你需要确保 Spring boot 扫描这个类,并且它是正确导入到你的 com.comcast.FileProcess.configuration.SprintgBatchConfiguration
中的。
我已将这些代码移至批处理配置并解决了问题。感谢@Mahmoud 的时间和帮助。以上是关于无法在春季批处理中序列化此事务的访问的主要内容,如果未能解决你的问题,请参考以下文章
TransactionRequiredException:没有事务正在进行春季批处理作业和休眠
Spring Batch ORA-08177: 运行单个作业时无法序列化此事务的访问,SERIALIZED 隔离级别