Re: LWLocks by LockManager slowing large DB

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I wrote:
> Andres Freund <andres@xxxxxxxxxxx> writes:
>> Cool. And damn: I can't immediately think of a way to optimize this to
>> not require this kind of hack in the future.

> Maybe the same thing we do with user tables, ie not give up the lock
> when we close a toast rel?  As long as the internal lock counters
> are 64-bit, we'd not have to worry about overflowing them.

Like this?  This passes check-world, modulo the one very-unsurprising
regression test change.  I've not tried to do any performance testing.

			regards, tom lane

diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c
index 545a6b8867..3826b4d93e 100644
--- a/src/backend/access/common/detoast.c
+++ b/src/backend/access/common/detoast.c
@@ -367,7 +367,7 @@ toast_fetch_datum(struct varlena *attr)
 								 * case. */
 
 	/*
-	 * Open the toast relation and its indexes
+	 * Open the toast relation (but its indexes are dealt with by the AM)
 	 */
 	toastrel = table_open(toast_pointer.va_toastrelid, AccessShareLock);
 
@@ -376,7 +376,7 @@ toast_fetch_datum(struct varlena *attr)
 									 attrsize, 0, attrsize, result);
 
 	/* Close toast table */
-	table_close(toastrel, AccessShareLock);
+	table_close(toastrel, NoLock);
 
 	return result;
 }
@@ -457,7 +457,7 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
 									 result);
 
 	/* Close toast table */
-	table_close(toastrel, AccessShareLock);
+	table_close(toastrel, NoLock);
 
 	return result;
 }
diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c
index 730cd04a2d..f0d0251ce0 100644
--- a/src/backend/access/common/toast_internals.c
+++ b/src/backend/access/common/toast_internals.c
@@ -27,7 +27,7 @@
 #include "utils/rel.h"
 #include "utils/snapmgr.h"
 
-static bool toastrel_valueid_exists(Relation toastrel, Oid valueid);
+static bool toastrel_valueid_exists(Relation toastrel, Oid valueid, LOCKMODE lock);
 static bool toastid_valueid_exists(Oid toastrelid, Oid valueid);
 
 /* ----------
@@ -264,7 +264,8 @@ toast_save_datum(Relation rel, Datum value,
 				 * be reclaimed by VACUUM.
 				 */
 				if (toastrel_valueid_exists(toastrel,
-											toast_pointer.va_valueid))
+											toast_pointer.va_valueid,
+											RowExclusiveLock))
 				{
 					/* Match, so short-circuit the data storage loop below */
 					data_todo = 0;
@@ -359,8 +360,8 @@ toast_save_datum(Relation rel, Datum value,
 	/*
 	 * Done - close toast relation and its indexes
 	 */
-	toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock);
-	table_close(toastrel, RowExclusiveLock);
+	toast_close_indexes(toastidxs, num_indexes, NoLock);
+	table_close(toastrel, NoLock);
 
 	/*
 	 * Create the TOAST pointer value that we'll return
@@ -440,8 +441,8 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative)
 	 * End scan and close relations
 	 */
 	systable_endscan_ordered(toastscan);
-	toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock);
-	table_close(toastrel, RowExclusiveLock);
+	toast_close_indexes(toastidxs, num_indexes, NoLock);
+	table_close(toastrel, NoLock);
 }
 
 /* ----------
@@ -453,7 +454,7 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative)
  * ----------
  */
 static bool
-toastrel_valueid_exists(Relation toastrel, Oid valueid)
+toastrel_valueid_exists(Relation toastrel, Oid valueid, LOCKMODE lock)
 {
 	bool		result = false;
 	ScanKeyData toastkey;
@@ -464,7 +465,7 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
 
 	/* Fetch a valid index relation */
 	validIndex = toast_open_indexes(toastrel,
-									RowExclusiveLock,
+									lock,
 									&toastidxs,
 									&num_indexes);
 
@@ -489,7 +490,7 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
 	systable_endscan(toastscan);
 
 	/* Clean up */
-	toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock);
+	toast_close_indexes(toastidxs, num_indexes, NoLock);
 
 	return result;
 }
@@ -508,9 +509,9 @@ toastid_valueid_exists(Oid toastrelid, Oid valueid)
 
 	toastrel = table_open(toastrelid, AccessShareLock);
 
-	result = toastrel_valueid_exists(toastrel, valueid);
+	result = toastrel_valueid_exists(toastrel, valueid, AccessShareLock);
 
-	table_close(toastrel, AccessShareLock);
+	table_close(toastrel, NoLock);
 
 	return result;
 }
diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index 55bbe1d584..c3bfb97c62 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -789,5 +789,5 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
 
 	/* End scan and close indexes. */
 	systable_endscan_ordered(toastscan);
-	toast_close_indexes(toastidxs, num_indexes, AccessShareLock);
+	toast_close_indexes(toastidxs, num_indexes, NoLock);
 }
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index ec14b060a6..b7a007904e 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2610,7 +2610,9 @@ select * from my_locks order by 1;
   relname  |       max_lockmode       
 -----------+--------------------------
  alterlock | ShareUpdateExclusiveLock
-(1 row)
+ pg_toast  | AccessShareLock
+ pg_toast  | AccessShareLock
+(3 rows)
 
 rollback;
 begin; alter table alterlock cluster on alterlock_pkey;

[Postgresql General]     [Postgresql PHP]     [PHP Users]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Yosemite]

  Powered by Linux