Java / Postgres:与Flyway清理死锁

时间:2017-01-27 13:08:08

标签: java postgresql spring-transactions flyway

我的PostgreSQL数据库上有一个计划任务(包括写作!):<​​/ p>

@Transactional
@Scheduled(fixedDelay = SCHEDULE_DELAY_IN_SECONDS * MILLISECONDS_PER_SECOND)
public synchronized void doStuff() {
    // snip
}

我确实为Flyway.clean()我的数据库提供了服务:

@Service
public class MyService {

    @Transactional
    public void deleteDatabase() {
        flyway.clean();
        flyway.migrate();

        // snip
    }
}

现在每隔一段时间删除数据库就会发生死锁:

26-Jan-2017 17:15:57.174 SEVERE [https-jsse-nio-8443-exec-4] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcher] in context with path [/foo] threw exception [Request processing failed; nested exception is org.flywaydb.core.api.FlywayException: Unable to drop "public"."bar"] with root cause
 org.postgresql.util.PSQLException: ERROR: deadlock detected
  Detail: Process 122 waits for AccessExclusiveLock on relation 69572 of database 16388; blocked by process 97.
Process 97 waits for AccessShareLock on relation 69575 of database 16388; blocked by process 122.
  Hint: See server log for query details.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2284)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2003)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:200)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:424)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:161)
    at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:155)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:198)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:198)
    at org.flywaydb.core.internal.dbsupport.JdbcTemplate.execute(JdbcTemplate.java:219)
    at org.flywaydb.core.internal.dbsupport.postgresql.PostgreSQLTable.doDrop(PostgreSQLTable.java:43)
    at org.flywaydb.core.internal.dbsupport.SchemaObject.drop(SchemaObject.java:80)
    at org.flywaydb.core.internal.dbsupport.postgresql.PostgreSQLSchema.doClean(PostgreSQLSchema.java:84)
    at org.flywaydb.core.internal.dbsupport.Schema.clean(Schema.java:148)
    at org.flywaydb.core.internal.command.DbClean$4.doInTransaction(DbClean.java:182)
    at org.flywaydb.core.internal.command.DbClean$4.doInTransaction(DbClean.java:180)
    at org.flywaydb.core.internal.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:72)
    at org.flywaydb.core.internal.command.DbClean.cleanSchema(DbClean.java:180)
    at org.flywaydb.core.internal.command.DbClean.clean(DbClean.java:130)
    at org.flywaydb.core.Flyway$3.execute(Flyway.java:1017)
    at org.flywaydb.core.Flyway$3.execute(Flyway.java:1013)
    at org.flywaydb.core.Flyway.execute(Flyway.java:1361)
    at org.flywaydb.core.Flyway.clean(Flyway.java:1013)
    at com.acme.MyService.deleteDatabase(MyService.java:54)
    // ...

我怀疑调度程序是另一个进程。怎么办?我会说Flyway - 作为更具侵略性的操作员,加上抛出错误的操作员 - 必须等待独占访问,但我如何以最有效的方式实现这一目标?特别是因为这两种方法都已经是@Transactional ...将

@Transactional(isolation = SERIALIZABLE)

帮助?这种隔离级别似乎是最具限制性的......或者它只是synchronized中缺失的deleteDatabase()?这种死锁有点难以重现,所以任何提示都会受到赞赏。

0 个答案:

没有答案