Re: LWLocks by LockManager slowing large DB - Mailing list pgsql-performance
| From | Tom Lane | 
|---|---|
| Subject | Re: LWLocks by LockManager slowing large DB | 
| Date | |
| Msg-id | 3428578.1618355806@sss.pgh.pa.us Whole thread Raw | 
| In response to | Re: LWLocks by LockManager slowing large DB (Tom Lane <tgl@sss.pgh.pa.us>) | 
| List | pgsql-performance | 
I wrote:
> Andres Freund <andres@anarazel.de> 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;
		
	pgsql-performance by date: