我正在针对PostgreSQL v12数据库进行开发。我正在使用SERIALIZABLE
交易。一般想法是,当PostgreSQL检测到序列化异常时,应重试整个事务。
我正在使用Spring的SERIALIZABLE
将数据库异常转换为Spring的异常类。该异常转换器应将PostgreSQL错误AbstractFallbackSQLExceptionTranslator
转换为AbstractFallbackSQLExceptionTranslator
。 Spring JDBC维护一个40001
/serialization_failure
来将PostgreSQL特定的代码40001
映射到数据库异常的通用serialization_failure
类,该类将API用户转换为ConcurrencyFailureException
。
我的想法是依靠Spring Retry项目重试ConcurrencyFailureException
事务,该事务由于以下序列化错误而暂停:
mapping file
在服务实现中,我只需将40001
替换为cannotSerializeTransactionCodes
并完成此操作。
现在,回到PostgreSQL。本质上,可以在两个阶段检测序列化异常:
[似乎Spring的ConcurrencyFailureException
正确地翻译了在执行一条语句时检测到的序列化异常,但在提交阶段未能转换该序列化异常。考虑以下堆栈跟踪:
SERIALIZABLE
您可以看到,PostgreSQL检测到序列化异常(@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Retryable(include = ConcurrencyFailureException.class, maxAttempts = ..., backoff = ...)
@Transactional(isolation = Isolation.SERIALIZABLE)
public @interface SerializableTransactionRetry {
}
),但是Spring将其转换为@Transactional
而不是@SerializableTransactionRetry
。
[我可以更改上面的AbstractFallbackSQLExceptionTranslator
注释,使其也包含org.springframework.transaction.TransactionSystemException: Could not commit JDBC transaction; nested exception is org.postgresql.util.PSQLException: ERROR: could not serialize access due to read/write dependencies among transactions
Detail: Reason code: Canceled on identification as a pivot, during commit attempt.
Hint: The transaction might succeed if retried.
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:332)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:91)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:287)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:164)
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:118)
at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
,但是我认为那是错误的,因为现在我们将重试任何类型的事务错误,这不是我们想要的。] >
这是Spring的ERROR: could not serialize access due to ...
的缺点吗?我正在使用Spring 5.2.1。
我正在针对PostgreSQL v12数据库进行开发。我正在使用SERIALIZABLE交易。一般想法是,当PostgreSQL检测到序列化异常时,应重试完整的...
如TransactionSystemException
中所述,TransactionSystemException
实际上未用于提交阶段发生的SQL异常。