summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Korotkov2024-02-11 22:33:44 +0000
committerAlexander Korotkov2024-02-11 22:52:25 +0000
commit8be93177c46b0f6a29a7376229b7ee002066d5f8 (patch)
tree1f74eb92722f4c9dbc84dc103f9fb38591f0f950
parent428e2de1b895079bbf50a128f8b3824679f4bb65 (diff)
Use heap_inplace_update() to unset pg_database.dathasloginevt
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. It's known that changes made by heap_inplace_update() may be lost due to concurrent normal updates. However, we are OK with that. The subsequent connections will still have a chance to set "dathasloginevt" to false. Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/e2a0248e-5f32-af0c-9832-a90d303c2c61%40gmail.com
-rw-r--r--src/backend/commands/event_trigger.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index f193c7ddf60..c8b662131c3 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,45 @@ 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.
+ *
+ * It's known that changes made by heap_inplace_update() may
+ * be lost due to concurrent normal updates. However, we are
+ * OK with that. The subsequent connections will still have a
+ * chance to set "dathasloginevt" to false.
+ */
+ heap_inplace_update(pg_db, tuple);
}
table_close(pg_db, RowExclusiveLock);
heap_freetuple(tuple);