From 0da5aaaedf20085cb078ac2ec5ede0f0cabcb86a Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Mon, 5 Feb 2024 01:46:41 +0200 Subject: [PATCH] Use heap_inplace_update() to unset pg_database.dathasloginevt Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/e2a0248e-5f32-af0c-9832-a90d303c2c61%40gmail.com --- src/backend/commands/event_trigger.c | 31 ++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index f193c7ddf60..da01b458dc3 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -13,6 +13,7 @@ */ #include "postgres.h" +#include "access/heapam.h" #include "access/htup_details.h" #include "access/table.h" #include "access/xact.h" @@ -943,18 +944,40 @@ EventTriggerOnLogin(void) Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock); HeapTuple tuple; Form_pg_database db; + ScanKeyData key[1]; + SysScanDesc scan; - tuple = SearchSysCacheCopy1(DATABASEOID, - ObjectIdGetDatum(MyDatabaseId)); + /* + * Get the pg_database tuple to scribble on. Note that this does + * not directly rely on the syscache to avoid issues with + * flattened toast values for the in-place update. + */ + ScanKeyInit(&key[0], + Anum_pg_database_oid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(MyDatabaseId)); + + scan = systable_beginscan(pg_db, DatabaseOidIndexId, true, + NULL, 1, key); + tuple = systable_getnext(scan); + tuple = heap_copytuple(tuple); + systable_endscan(scan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); + elog(ERROR, "could not find tuple for database %u", MyDatabaseId); db = (Form_pg_database) GETSTRUCT(tuple); if (db->dathasloginevt) { db->dathasloginevt = false; - CatalogTupleUpdate(pg_db, &tuple->t_self, tuple); + + /* + * Do an "in place" update of the pg_database tuple. Doing + * this instead of regular updates serves two purposes. + * First, that avoids possible waiting on the row-level lock. + * Second, that avoids dealing with TOAST. + */ + heap_inplace_update(pg_db, tuple); } table_close(pg_db, RowExclusiveLock); heap_freetuple(tuple); -- 2.39.3 (Apple Git-145)