diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index c895876..a85d792 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -254,6 +254,8 @@ static HTAB *LockMethodLockHash; static HTAB *LockMethodProcLockHash; static HTAB *LockMethodLocalHash; +/* Initial size of LockMethodLocalHash table */ +#define LOCKMETHODLOCALHASH_INIT_SIZE 16 /* private state for error cleanup */ static LOCALLOCK *StrongLockInProgress; @@ -339,6 +341,7 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP) #endif /* not LOCK_DEBUG */ +static void CreateLocalLockHash(void); static uint32 proclock_hash(const void *key, Size keysize); static void RemoveLocalLock(LOCALLOCK *locallock); static PROCLOCK *SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, @@ -431,6 +434,19 @@ InitLocks(void) if (!found) SpinLockInit(&FastPathStrongRelationLocks->mutex); + CreateLocalLockHash(); +} + +/* + * CreateLocalLockHash + * Create the LockMethodLocalHash hash table. + */ +static void +CreateLocalLockHash(void) +{ + static HTAB *htab; + HASHCTL info; + /* * Allocate non-shared hash table for LOCALLOCK structs. This stores lock * counts and resource owner information. @@ -447,12 +463,11 @@ InitLocks(void) info.entrysize = sizeof(LOCALLOCK); LockMethodLocalHash = hash_create("LOCALLOCK hash", - 16, + LOCKMETHODLOCALHASH_INIT_SIZE, &info, HASH_ELEM | HASH_BLOBS); } - /* * Fetch the lock method table associated with a given lock */ @@ -2349,6 +2364,17 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks) LWLockRelease(partitionLock); } /* loop over partitions */ + /* + * The hash_seq_search can become inefficient when the hash table has + * grown significantly larger than the default size due to the backend + * having run queries which obtained large numbers of locks at once. Here + * we'll build a new table at its initial size whenever the table is empty + * and has expanded from its original size. + */ + if (status.curBucket > LOCKMETHODLOCALHASH_INIT_SIZE && + hash_get_num_entries(LockMethodLocalHash) == 0) + CreateLocalLockHash(); + #ifdef LOCK_DEBUG if (*(lockMethodTable->trace_flag)) elog(LOG, "LockReleaseAll done");