From d09dddcac5a7947aab78925ccdaa1df9bd875685 Mon Sep 17 00:00:00 2001 From: ChangAo Chen Date: Thu, 14 May 2026 13:05:32 +0800 Subject: [PATCH v1] Make log_lock_failures support LOCK NOWAIT --- doc/src/sgml/config.sgml | 9 +++++---- src/backend/catalog/namespace.c | 6 +++++- src/backend/commands/lockcmds.c | 18 +++++++++++++++--- src/backend/commands/repack.c | 4 ++-- src/backend/commands/tablecmds.c | 2 +- src/backend/commands/vacuum.c | 2 +- src/backend/postmaster/autovacuum.c | 2 +- src/backend/storage/lmgr/lmgr.c | 4 ++-- src/include/catalog/namespace.h | 1 + src/include/storage/lmgr.h | 2 +- 10 files changed, 34 insertions(+), 16 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 73cc0412330..f4cf888e813 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -8373,10 +8373,11 @@ log_line_prefix = '%m [%p] %q%u@%d/%a ' Controls whether a detailed log message is produced when a lock acquisition fails. This is useful for analyzing the causes of lock failures. Currently, only lock failures - due to SELECT NOWAIT is supported. - The default is off. Only superusers and - users with the appropriate SET privilege - can change this setting. + due to SELECT NOWAIT and + LOCK NOWAIT is supported. The default is + off. Only superusers and users with the + appropriate SET privilege can change this + setting. diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 56b87d878e8..d7ddeec53ce 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -429,6 +429,9 @@ spcache_insert(const char *searchPath, Oid roleid) * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait * for a lock. * + * If flags contains RVR_LOG_LOCK_FAILURE, log lock failure if we'd have + * to wait for a lock. + * * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED. * * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a @@ -591,7 +594,8 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, AcceptInvalidationMessages(); else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED))) LockRelationOid(relId, lockmode); - else if (!ConditionalLockRelationOid(relId, lockmode)) + else if (!ConditionalLockRelationOid(relId, lockmode, + (flags & RVR_LOG_LOCK_FAILURE))) { int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR; diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index f66b8f17b9b..0043dc96773 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -23,6 +23,7 @@ #include "nodes/nodeFuncs.h" #include "rewrite/rewriteHandler.h" #include "storage/lmgr.h" +#include "storage/lock.h" #include "utils/acl.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -50,9 +51,18 @@ LockTableCommand(LockStmt *lockstmt) RangeVar *rv = (RangeVar *) lfirst(p); bool recurse = rv->inh; Oid reloid; + uint32 flags = 0; + + if (lockstmt->nowait) + { + flags |= RVR_NOWAIT; + + if (log_lock_failures) + flags |= RVR_LOG_LOCK_FAILURE; + } reloid = RangeVarGetRelidExtended(rv, lockstmt->mode, - lockstmt->nowait ? RVR_NOWAIT : 0, + flags, RangeVarCallbackForLockTable, &lockstmt->mode); @@ -131,7 +141,8 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait) if (!nowait) LockRelationOid(childreloid, lockmode); - else if (!ConditionalLockRelationOid(childreloid, lockmode)) + else if (!ConditionalLockRelationOid(childreloid, lockmode, + log_lock_failures)) { /* try to throw error by name; relation could be deleted... */ char *relname = get_rel_name(childreloid); @@ -217,7 +228,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context) /* We have enough rights to lock the relation; do so. */ if (!context->nowait) LockRelationOid(relid, context->lockmode); - else if (!ConditionalLockRelationOid(relid, context->lockmode)) + else if (!ConditionalLockRelationOid(relid, context->lockmode, + log_lock_failures)) ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s\"", diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index fae88d6bb83..136e7f15977 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -2129,7 +2129,7 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt) * disregard it. Be sure to release this if we ultimately decide * not to process the table! */ - if (!ConditionalLockRelationOid(index->indrelid, AccessShareLock)) + if (!ConditionalLockRelationOid(index->indrelid, AccessShareLock, false)) continue; /* Verify that the table still exists; skip if not */ @@ -2188,7 +2188,7 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt) * disregard the table. Be sure to release this if we ultimately * decide not to process the table! */ - if (!ConditionalLockRelationOid(class->oid, AccessShareLock)) + if (!ConditionalLockRelationOid(class->oid, AccessShareLock, false)) continue; /* Verify that the table still exists */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 92b0f38c353..fd50a4c4f21 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -17373,7 +17373,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt) NameStr(relForm->relname)); if (stmt->nowait && - !ConditionalLockRelationOid(relOid, AccessExclusiveLock)) + !ConditionalLockRelationOid(relOid, AccessExclusiveLock, false)) ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("aborting because lock on relation \"%s.%s\" is not available", diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index a4abb29cf64..7bd13421093 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -789,7 +789,7 @@ vacuum_open_relation(Oid relid, RangeVar *relation, uint32 options, */ if (!(options & VACOPT_SKIP_LOCKED)) rel = try_relation_open(relid, lmode); - else if (ConditionalLockRelationOid(relid, lmode)) + else if (ConditionalLockRelationOid(relid, lmode, false)) rel = try_relation_open(relid, NoLock); else { diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index a5a8db2ff88..550c38d3ed7 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -2220,7 +2220,7 @@ do_autovacuum(void) * somebody else is using (or dropping) the table, so it's not our * concern anymore. Having the lock prevents race conditions below. */ - if (!ConditionalLockRelationOid(relid, AccessExclusiveLock)) + if (!ConditionalLockRelationOid(relid, AccessExclusiveLock, false)) continue; /* diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 2ccf7237fee..29871105416 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -148,7 +148,7 @@ LockRelationOid(Oid relid, LOCKMODE lockmode) * LockXXX routines in this file, but they could easily be added if needed. */ bool -ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode) +ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode, bool logLockFailure) { LOCKTAG tag; LOCALLOCK *locallock; @@ -157,7 +157,7 @@ ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode) SetLocktagRelationOid(&tag, relid); res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock, - false); + logLockFailure); if (res == LOCKACQUIRE_NOT_AVAIL) return false; diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 9453a3e4932..cae2c2f53ec 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -90,6 +90,7 @@ typedef enum RVROption RVR_MISSING_OK = 1 << 0, /* don't error if relation doesn't exist */ RVR_NOWAIT = 1 << 1, /* error if relation cannot be locked */ RVR_SKIP_LOCKED = 1 << 2, /* skip if relation cannot be locked */ + RVR_LOG_LOCK_FAILURE = 1 << 3, /* log failure if relation cannot be locked */ } RVROption; typedef void (*RangeVarGetRelidCallback) (const RangeVar *relation, Oid relId, diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index 2a985ce5e15..7a31a90e8c9 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -39,7 +39,7 @@ extern void RelationInitLockInfo(Relation relation); /* Lock a relation */ extern void LockRelationOid(Oid relid, LOCKMODE lockmode); extern void LockRelationId(LockRelId *relid, LOCKMODE lockmode); -extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode); +extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode, bool logLockFailure); extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode); extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode); -- 2.34.1