在 postgresql 上使用 delete 时出现死锁

Deadlock when using delete on postgresql

我正在使用 postgres。我在 java 中编写代码。制作了一个定期从数据库中删除行的线程池(deleteJobPeriodMs = 10 秒):

long DELETEJOBPERIOD_MS_DEFAULT = 10000;
long deleteJobPeriodMs = userVariableDeleteJobPeriod.haveVariable()? deleteJobPeriodMsVar.getVariable(): DELETEJOBPERIOD_MS_DEFAULT;
executorService = new ScheduledThreadPoolExecutor(coreThreadsCount, this::createDeleteJobThread);
executorService.scheduleAtFixedRate(this::deleteMethod, 0, 
deleteJobPeriodMs, TimeUnit.MILLISECONDS);

deleteMethod 使用以下请求:DELETE FROM field WHERE delete_date < ?

与此同时,新条目不断添加到需要进一步删除的程序中。不执行其他操作。每小时操作大约发生 5-10 次死锁。这是我在日志中得到的内容:

2021-05-22 00:16:01 MSK [117890]: [1-1] ERROR:  deadlock detected
2021-05-22 00:16:01 MSK [117890]: [2-1] DETAIL:  Process 117890 waits for 
AccessExclusiveLock on tuple (17724,12) of relation 471906 of database 471895; 
blocked by process 116805.
    Process 116805 waits for ShareLock on transaction 1923461368; blocked by process 115793.
    Process 115793 waits for ShareLock on transaction 1923460316; blocked by process 109269.
    Process 109269 waits for ShareLock on transaction 1923457105; blocked by process 117890.
    Process 117890: DELETE FROM field WHERE delete_date < 
    Process 116805: DELETE FROM field WHERE delete_date < 
    Process 115793: DELETE FROM field WHERE delete_date < 
    Process 109269: DELETE FROM field WHERE delete_date < 
2021-05-22 00:16:01 MSK [117890]: [3-1] HINT:  See server log for query details.
2021-05-22 00:16:01 MSK [117890]: [4-1] STATEMENT:  DELETE FROM jobs WHERE delete_date < 

堆栈跟踪之一的一部分:

Exception: operation: DeleteService.onDeleteFields, cause:
org.postgresql.util.PSQLException: ERROR: deadlock detected
  Detail: Process 127116 waits for ShareLock on transaction 1610026614; blocked by process 6433.
Process 6433 waits for ShareLock on transaction 1610014636; blocked by process 5957.
Process 5957 waits for AccessExclusiveLock on tuple (3,5) of relation 471906 of database 471895; blocked by process 127116.
  Hint: See server log for query details.
  Where: while deleting tuple (3,5) in relation "field"
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:132)
    at jdk.internal.reflect.GeneratedMethodAccessor38.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:428)
    at com.sun.proxy.$Proxy7.executeUpdate(Unknown Source)

请务必注意,其中多个应用程序部署在同一数据库上

已将请求从 DELETE FROM field WHERE delete_date < ? 更改为 DELETE FROM JOBS WHERE fid IN (SELECT fid FROM JOBS WHERE delete_date < ? FOR UPDATE SKIP LOCKED)。目前没有出现错误。