我正在尝试从 springBoot 2.5 迁移到 2.7,并注意到有时我会遇到 重复数据输入时的 SQLINtegrityConstraintViolation
2024-05-06 17:19:30.929 WARN 6556 --- [nio-9012-exec-2] o.m.jdbc.message.server.ErrorPacket : Error: 1062-23000: Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
2024-05-06 17:19:30.930 INFO 6556 --- [nio-9012-exec-2] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2024-05-06 17:19:30.931 ERROR 6556 --- [nio-9012-exec-2] o.h.e.jdbc.batch.internal.BatchingBatch : HHH000315: Exception executing batch [java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'], SQL: update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?
2024-05-06 17:19:30.931 WARN 6556 --- [nio-9012-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2024-05-06 17:19:30.931 ERROR 6556 --- [nio-9012-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
2024-05-06 17:19:30.941 ERROR 6556 --- [nio-9012-exec-2] c.d.r.u.service.impl.TestingServiceImpl : error is could not execute batch; SQL [update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch
2024-05-06 17:19:30.944 ERROR 6556 --- [nio-9012-exec-2] c.d.r.u.service.impl.TestingServiceImpl : full msg
org.springframework.dao.DataIntegrityViolationException: could not execute batch; SQL [update t_instance set ask=?, ask1=?, ask2=?, assetType=?, attrChangeId=?, bid=?, bid1=?, bid2=?, bkgdref=?, closing=?, comments=?, contributor=?, createdby=?, crud=?, curvespreadask=?, curvespreadbid=?, curvespreadmid=?, date1=?, date2=?, dimChangeId=?, distributioncount=?, faquotation=?, hasSubRates=?, historicclose=?, holidayflag=?, instanceupdatedby=?, instanceupdateddate=?, intraflag=?, last=?, lockstatus=?, manualuploadfilename=?, maturitysource=?, mid=?, mid1=?, mid2=?, ops=?, pricingsource=?, quoteunits=?, radCheck=?, reasoncodeid=?, recorddate=?, resrccnt=?, singleContributor=?, spread=?, srccurrency=?, srcfavor=?, srcstrike=?, statusid=?, subRateSnapId=?, T_1_DATE=?, trailingdate=?, triggerOrion=?, txId=?, updatedby=?, updateddate=?, usedInfo=?, violationid=?, workingdayflag=?, yieldask=?, yieldbid=?, yieldmid=? where locationId=? and rateId=?]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute batch
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241)
at jdk.proxy2/jdk.proxy2.$Proxy257.saveAll(Unknown Source)
at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl.testingLoop(TestingServiceImpl.java:38)
at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl$$FastClassBySpringCGLIB$$ff8f61f1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
at com.mycompany.trax.uiservice.service.impl.TestingServiceImpl$$EnhancerBySpringCGLIB$$323b0328.testingLoop(<generated>)
at com.mycompany.trax.uiservice.controller.TestingController.test(TestingController.java:27)
at com.mycompany.trax.uiservice.controller.TestingController$$FastClassBySpringCGLIB$$3c8d5603.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
at com.mycompany.trax.uiservice.controller.TestingController$$EnhancerBySpringCGLIB$$8e3c1a27.test(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at com.mycompany.trax.uiservice.filter.TimeZoneFilter.doFilterInternal(TimeZoneFilter.java:109)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute batch
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:109)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:135)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:110)
at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:153)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:198)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3303)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2438)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
... 109 common frames omitted
Caused by: java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
at org.mariadb.jdbc.export.ExceptionFactory.createBatchUpdate(ExceptionFactory.java:181)
at org.mariadb.jdbc.ClientPreparedStatement.executeBatchBulk(ClientPreparedStatement.java:179)
at org.mariadb.jdbc.ClientPreparedStatement.executeInternalPreparedBatch(ClientPreparedStatement.java:115)
at org.mariadb.jdbc.ClientPreparedStatement.executeBatch(ClientPreparedStatement.java:466)
at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:127)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:125)
... 129 common frames omitted
Caused by: java.sql.BatchUpdateException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
at org.mariadb.jdbc.export.ExceptionFactory.createBatchUpdate(ExceptionFactory.java:215)
at org.mariadb.jdbc.client.impl.StandardClient.executePipeline(StandardClient.java:637)
at org.mariadb.jdbc.ClientPreparedStatement.executeBatchBulk(ClientPreparedStatement.java:148)
... 134 common frames omitted
Caused by: java.sql.SQLIntegrityConstraintViolationException: (conn=9469435) Duplicate entry '101-2024-05-06-105285213-8888-12-31 23:59:59.000000-BD' for key 'PRIMARY'
at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:290)
at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:370)
at org.mariadb.jdbc.message.ClientMessage.readPacket(ClientMessage.java:134)
at org.mariadb.jdbc.client.impl.StandardClient.readPacket(StandardClient.java:872)
at org.mariadb.jdbc.client.impl.StandardClient.readResults(StandardClient.java:811)
at org.mariadb.jdbc.client.impl.StandardClient.readResponse(StandardClient.java:730)
at org.mariadb.jdbc.client.impl.StandardClient.executePipeline(StandardClient.java:571)
... 135 common frames omitted
重复实际上是由从 t_instance 复制到 h_instance 的触发器引起的,在调试时,我们注意到,如果系统尝试更新 15 条记录,它实际上更新了 1 条记录 14-15 次, 并通过以下方式将字段复制到 h_instance数据库触发器具有相同的rateid,这将导致触发器抛出错误。
抛出此错误的代码在这里,这是一个检索并立即保存记录的简单方法。通常此方法每次触发时会保存 5 - 100 条记录。它不包含重复项,因为传递的集合 (rateIds) 通常是一个 Set。
@Autowired
private InstanceRepository instanceRepo;
@Transactional
public void testingLoop(){
try {
long[] instances = {105497181, 105285213, 105321169}; //500 records, here only shown 3...
List<Long> instanceIdList = Arrays.stream(instances).boxed().collect(Collectors.toList());
List<Instance> items = instanceRepo.findByRateIdInAndLocationid(instanceIdList, 101);
if (items != null && !items.isEmpty()) {
logger.info("records found:{}", items.size());
for (Instance item : items) {
item.setStatusid(10);
item.setAsk("1.23");
item.setBid("1.23");
item.setMid("1.23");
}
instanceRepo.saveAll(items);
}
}catch(Exception e){
logger.error("error is {}",e.getMessage());
logger.error("full msg",e);
}
}
数据源
@Configuration
@EnableTransactionManagement
@EnableBatchProcessing
@EnableAutoConfiguration
@EnableJpaRepositories(basePackages = {
"com.mycompany.trax.db.reliable.repo"}, entityManagerFactoryRef = "reliableEntityManagerFactory", transactionManagerRef = "reliableTransactionManager")
public class ReliableDS {
private final Logger logger = RMSLogger.getLogger(this.getClass());
@Autowired
private ReliableEntityInterceptor entityInterceptor;
@Bean(name = "reliableDataSource")
@ConfigurationProperties(prefix = "spring.datasource.reliable")
public DataSource reliableDataSource() {
//DataSource ds = DataSourceBuilder.create().build();
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.mariadb.jdbc.Driver");
return dataSourceBuilder.build();
}
@Bean(name = "reliableEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean reliableEntityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// show hibernate generated SQl
//vendorAdapter.setShowSql(true);
Map<String, Object> jpaProperties = new HashMap<String, Object>();
if(entityInterceptor != null) {
//jpaProperties.put("hibernate.session_factory.interceptor", entityInterceptor);
jpaProperties.put("hibernate.order_inserts", Boolean.TRUE);
jpaProperties.put("hibernate.order_updates", Boolean.TRUE);
jpaProperties.put("hibernate.jdbc.batch_size", 20);
jpaProperties.put("hibernate.jdbc.fetch_size", 400);
}
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(reliableDataSource());
em.setJpaPropertyMap(jpaProperties);
em.setPackagesToScan("com.mycompany.trax.db.reliable.entity","com.mycompany.trax.db.reliable.modelentity");
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
@Bean(name = "reliableTransactionManager")
public PlatformTransactionManager reliableTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(reliableEntityManagerFactory().getObject());
return transactionManager;
}
@Bean(name="reliableJdbcTemplate")
public NamedParameterJdbcTemplate jdbcTemplate(){
return new NamedParameterJdbcTemplate(reliableDataSource());
}
}
实体:
@Data
@Entity
@Table(name = "t_instance")
@IdClass(InstancePK.class)
@EntityListeners(InstanceListener.class)
@NoArgsConstructor
public class Instance implements Serializable {
private static final long serialVersionUID = 1L;
/** The Attr change id. */
private String attrChangeId;
/** The Used info. */
@JsonProperty("usedinfo")
public String usedInfo;
@Id
@Column(name = "rateId",updatable=false)
private Long rateId;
@Id
@Column(name = "locationId",updatable=false)
private Integer locationid;
private String ask;
//and another 50 more fields....
}
我们还注意到,如果我们只使用 save() (逐一保存实体),或者将批量大小设置为 1,它不会返回任何问题。
知道为什么带有 saveAll() 的 spring 批处理在这里不起作用吗?
我还启用了休眠日志(使用活页夹),并且我只能看到数据库中存在问题的rateid的1个更新
其他信息:
触发: 更新前 创建定义器=
USERADMIN
@%
在每行开始更新TRG_BU_T_INSTANCE
之前触发t_instance
设置新的.ATTRCHANGEID=UUID();
结束
更新后(简化 - 仍然有问题,详细信息 创建定义器=
USERADMIN
@%
在每行开始更新TRG_AU_T_INSTANCE
后触发t_instancetest
插入 t_datalog
( RateId
, CreatedDate
) 值 (OLD.RATEID, sysdate());
结束
准备声明: n.t.d.l.l.SLF4JQueryLoggingListener : {"name":"reliableDataSource", "connection":3, "time":13, "success":true, "type":"Prepared", "batch":true, "querySize":1, “batchSize”:7,“查询”:[“更新t_instancetest设置ask=?,bid=?,createdby=?,crud=?,instanceupdateddate=?,locationId=?,mid=?,updatedby=?,updateddate=?其中 locationid=? 和rateId=?"], "params":[["116.13","12.23","SYSTEM","U","2024-05-10 12:31:59.665","101", "7181","娜迦","2024-05-10 12:03:55.0","101","7181"],["116.13","12.23","系统","U","2024- 05-10 12:31:59.665","101","7239","娜迦","2024-05-10 12:03:55.0","101","7239"],["116.13"," 12.23","系统","U","2024-05-10 12:31:59.665","101","7254","纳迦","2024-05-10 12:03:55.0"," 101","7254"],["116.13","12.23","系统","U","2024-05-10 12:31:59.665","101","7265","纳迦", "2024-05-10 12:03:55.0","101","7265"],["116.13","12.23","系统","U","2024-05-10 12:31:59.665 ","101","7370","娜迦","2024-05-10 12:03:55.0","101","7370"],["116.13","12.23","系统"," U","2024-05-10 12:31:59.665","101","7453","纳迦","2024-05-10 12:03:55.0","101","7453"], [“116.13”,“12.23”,“系统”,“U”,“2024-05-10 12:31:59.665”,“101”,“7643”,“纳迦”,“2024-05-10 12: 03:55.0","101","7643"]]}
我在下面的答案中包含了 mariadb 日志,因为正文限制为 30k 个字符。
不是真正的答案。添加观察到但无法放入 30k 问题主体的行为。
似乎是由触发器引起的,因为虽然preparedstatement看起来不错,但mariadb日志不同。看起来它可以重复运行触发器 7 次。如果我们松开扳机,情况就会恢复正常。
#240509 17:27:01 server id 2 end_log_pos 127297238 CRC32 0x5e6a5fa7 Write_rows: table id 3067 flags: STMT_END_F
### UPDATE `rms_reliabledb`.`t_instance`
### WHERE
### @1=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2='12.23' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @3='116.13' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @4='' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @5='2024-05-09 16:49:54.962888' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
### @6='2024-05-09 17:22:52.812000' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
### @7='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @8='U' /* VARSTRING(3) meta=3 nullable=1 is_null=0 */
### @9='SYSTEM' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @10='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @11=101 /* INT meta=0 nullable=0 is_null=0 */
### SET
### @1=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2='12.23' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @3='116.13' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @4='7181' /* VARSTRING(75) meta=75 nullable=1 is_null=0 */
### @5='2024-05-09 16:49:54.962888' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
### @6='2024-05-09 17:27:01.116000' /* DATETIME(6) meta=6 nullable=1 is_null=0 */
### @7='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @8='U' /* VARSTRING(3) meta=3 nullable=1 is_null=0 */
### @9='SYSTEM' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @10='naga' /* VARSTRING(90) meta=90 nullable=1 is_null=0 */
### @11=101 /* INT meta=0 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=98 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=99 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=100 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=101 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=102 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
### INSERT INTO `rms_reliabledb`.`t_datalog`
### SET
### @1=103 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2=7181 /* LONGINT meta=0 nullable=0 is_null=0 */
### @3='2024-05-09 17:27:01.000000' /* DATETIME(6) meta=6 nullable=0 is_null=0 */
# Number of rows: 7
# at 127297238
#240509 17:27:01 server id 2 end_log_pos 127297269 CRC32 0xd7928418 Xid = 205571784
COMMIT/*!*/;
下面还有长触发器(更新之前),后来被简化为仅插入数据日志。
CREATE DEFINER=`USERADMIN`@`%` TRIGGER `TRG_AU_T_INSTANCE` AFTER UPDATE ON `t_instance` FOR EACH ROW BEGIN
DECLARE v_current_time DATETIME(6);
DECLARE v_sys_eff_end_dt DATETIME;
DECLARE v_attr_json_str LONGTEXT;
SET v_current_time= CURTIME(6);
SET v_sys_eff_end_dt='8888-12-31 23:59:59';
SET v_attr_json_str = CONCAT('{ "ASK":"', IFNULL(NEW.ASK,''),
'","BID":"',IFNULL(NEW.BID,''),
'","MID":"',IFNULL(NEW.MID,''),
'","YIELDBID":"',IFNULL(NEW.YIELDBID,''),
'","YIELDMID":"',IFNULL(NEW.YIELDMID,''),
'","YIELDASK":"',IFNULL(NEW.YIELDASK,''),
'","MATURITYSOURCE":"',IFNULL(NEW.MATURITYSOURCE,''),
'","LAST":"',IFNULL(NEW.LAST,''),
'","CLOSING":"',IFNULL(NEW.CLOSING,''),
'","PRICINGSOURCE":"',IFNULL(NEW.PRICINGSOURCE,''),
'","HISTORICCLOSE":"',IFNULL(NEW.HISTORICCLOSE,''),
'","CURVESPREADASK":"',IFNULL(NEW.CURVESPREADASK,''),
'","CURVESPREADBID":"',IFNULL(NEW.CURVESPREADBID,''),
'","CURVESPREADMID":"',IFNULL(NEW.CURVESPREADMID,''),
'","BKGDREF":"',IFNULL(NEW.BKGDREF,''),
'","MANUALUPLOADFILENAME":"',IFNULL(NEW.MANUALUPLOADFILENAME,''),
'","CONTRIBUTOR":"',IFNULL(NEW.CONTRIBUTOR,''),
'","MID1":"',IFNULL(NEW.MID1,''),
'","MID2":"',IFNULL(NEW.MID2,''),
'","SRCFAVOR":"',IFNULL(NEW.SRCFAVOR,''),
'","ASK1":"',IFNULL(NEW.ASK1,''),
'","ASK2":"',IFNULL(NEW.ASK2,''),
'","BID1":"',IFNULL(NEW.BID1,''),
'","BID2":"',IFNULL(NEW.BID2,''),
'","DATE1":"',IFNULL(NEW.DATE1,''),
'","QUOTEUNITS":"',IFNULL(NEW.QUOTEUNITS,''),
'","DATE2":"',IFNULL(NEW.DATE2,''),
'","FAQUOTATION":"',IFNULL(NEW.FAQUOTATION,''),
'","SRCSTRIKE":"',IFNULL(NEW.SRCSTRIKE,''),
'","SRCCURRENCY":"',IFNULL(NEW.SRCCURRENCY,''),
'","RESRCCNT":"',IFNULL(NEW.RESRCCNT,''),
'","SPREAD":"',IFNULL(NEW.SPREAD,''),
'","SINGLECONTRIBUTOR":"',IFNULL(NEW.SINGLECONTRIBUTOR,''),
'","TRAILINGDATE":"',IFNULL(NEW.TRAILINGDATE,''),'"}');
UPDATE H_INSTANCE hi
SET hi.SYS_EFF_END_DT=DATE_SUB(v_current_time, INTERVAL 1 MICROSECOND)
WHERE hi.LOCATIONID=NEW.LOCATIONID
AND hi.RECORDDATE=NEW.RECORDDATE
AND hi.RATEID=NEW.RATEID
AND hi.sys_eff_end_dt=v_sys_eff_end_dt
AND hi.AssetType=NEW.ASSETTYPE;
INSERT INTO H_INSTANCE
(
LOCATIONID
,RECORDDATE
,RATEID
,ASSETTYPE
,STATUSID
,RATEATTRJSON
,LOCKSTATUS
,DISTRIBUTIONCOUNT
,REASONCODEID
,COMMENTS
,OPS
,HOLIDAYFLAG
,WORKINGDAYFLAG
,T_1_DATE
,INTRAFLAG
,VIOLATIONID
,INSTANCEUPDATEDBY
,INSTANCEUPDATEDDATE
,CREATEDBY
,CREATEDDATE
,UPDATEDBY
,UPDATEDDATE
,SYS_EFF_BEG_DT
,SYS_EFF_END_DT
,DimChangeId
,AttrChangeId
,UsedInfo
,SessionInfo
,TriggerOrion
,Txid
,HasSubRates
)
VALUES (
NEW.LOCATIONID
,NEW.RECORDDATE
,NEW.RATEID
,NEW.ASSETTYPE
,NEW.STATUSID
,v_attr_json_str
,NEW.LOCKSTATUS
,NEW.DISTRIBUTIONCOUNT
,NEW.REASONCODEID
,NEW.COMMENTS
,NEW.OPS
,NEW.HOLIDAYFLAG
,NEW.WORKINGDAYFLAG
,NEW.T_1_DATE
,NEW.INTRAFLAG
,NEW.VIOLATIONID
,NEW.INSTANCEUPDATEDBY
,NEW.INSTANCEUPDATEDDATE
,NEW.CREATEDBY
,NEW.CREATEDDATE
,NEW.UPDATEDBY
,NEW.UPDATEDDATE
,v_current_time
,v_sys_eff_end_dt
,NEW.DimChangeId
,NEW.AttrChangeId
,NEW.UsedInfo
,Fn_UTIL_Get_SessionInfo()
,NEW.TriggerOrion
,NEW.Txid
,NEW.HasSubRates
);
END