在 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)
。目前没有出现错误。
我正在使用 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)
。目前没有出现错误。