问题描述
我正在使用spring-integration创建分布式锁。像在org.springframework.integration.jdbc.lock.DefaultLockRepository#acquire
中一样,拥有DuplicateKeyExceptions
是正常的,我认为当另一个节点已经持有该锁时,这种情况将被显式处理。
但是,在违反唯一约束的情况下,使用Postgres时,我没有得到DuplicateKeyException,而是本地org.postgresql.util.PsqlException
:
Caused by: org.postgresql.util.PsqlException: ERROR: duplicate key value violates unique constraint "int_lock_pk"
Detail: Key (lock_key,region)=(2c294c0e-ff49-4e14-8d3e-d5c04ef269d8,DEFAULT) already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2477)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2190)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.springframework.jdbc.core.JdbcTemplate.lambda$update$0(JdbcTemplate.java:867)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:862)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:917)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:927)
at org.springframework.integration.jdbc.lock.DefaultLockRepository.acquire(DefaultLockRepository.java:163)
此情况不是 处理,并且锁获取中止。我该如何应对?
干杯, 斯蒂芬
编辑:异常包装在
Caused by: org.springframework.jdbc.UncategorizedsqlException: PreparedStatementCallback; uncategorized sqlException for sql [DELETE FROM INT_LOCK WHERE REGION=? AND LOCK_KEY=? AND CREATED_DATE<?]; sql state [25P02]; error code [0]; ERROR: current transaction is aborted,commands ignored until end of transaction block; nested exception is org.postgresql.util.PsqlException: ERROR: current transaction is aborted,commands ignored until end of transaction block
解决方法
您可以在自己的扩展名中覆盖DefaultLockRepository.acquire()
来捕获该异常并分别执行逻辑。
另一方面,不清楚SQLErrorCodeSQLExceptionTranslator
为什么不能正确处理此类异常。
根据现成的配置,Postgres编码如下:
<bean id="PostgreSQL" name="Postgres" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="useSqlStateForTranslation">
<value>true</value>
</property>
<property name="badSqlGrammarCodes">
<value>03000,42000,42601,42602,42622,42804,42P01</value>
</property>
<property name="duplicateKeyCodes">
<value>23505</value>
</property>
因此,没有显示25P02
。不知道发生了什么。
我们可能可以提供一个覆盖的DefaultLockRepository
指针来注入一个JdbcTemplate
,以便您提供自定义的SQLErrorCodeSQLExceptionTranslator
来处理这种异常。
但这太多了:我想说重写该方法并捕获这样的异常将是更简单的解决方案。