Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8be9317

Browse files
committed
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
1 parent 428e2de commit 8be9317

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

src/backend/commands/event_trigger.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
#include "postgres.h"
1515

16+
#include "access/heapam.h"
1617
#include "access/htup_details.h"
1718
#include "access/table.h"
1819
#include "access/xact.h"
@@ -943,18 +944,45 @@ EventTriggerOnLogin(void)
943944
Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
944945
HeapTuple tuple;
945946
Form_pg_database db;
947+
ScanKeyData key[1];
948+
SysScanDesc scan;
946949

947-
tuple = SearchSysCacheCopy1(DATABASEOID,
948-
ObjectIdGetDatum(MyDatabaseId));
950+
/*
951+
* Get the pg_database tuple to scribble on. Note that this does
952+
* not directly rely on the syscache to avoid issues with
953+
* flattened toast values for the in-place update.
954+
*/
955+
ScanKeyInit(&key[0],
956+
Anum_pg_database_oid,
957+
BTEqualStrategyNumber, F_OIDEQ,
958+
ObjectIdGetDatum(MyDatabaseId));
959+
960+
scan = systable_beginscan(pg_db, DatabaseOidIndexId, true,
961+
NULL, 1, key);
962+
tuple = systable_getnext(scan);
963+
tuple = heap_copytuple(tuple);
964+
systable_endscan(scan);
949965

950966
if (!HeapTupleIsValid(tuple))
951-
elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
967+
elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
952968

953969
db = (Form_pg_database) GETSTRUCT(tuple);
954970
if (db->dathasloginevt)
955971
{
956972
db->dathasloginevt = false;
957-
CatalogTupleUpdate(pg_db, &tuple->t_self, tuple);
973+
974+
/*
975+
* Do an "in place" update of the pg_database tuple. Doing
976+
* this instead of regular updates serves two purposes. First,
977+
* that avoids possible waiting on the row-level lock. Second,
978+
* that avoids dealing with TOAST.
979+
*
980+
* It's known that changes made by heap_inplace_update() may
981+
* be lost due to concurrent normal updates. However, we are
982+
* OK with that. The subsequent connections will still have a
983+
* chance to set "dathasloginevt" to false.
984+
*/
985+
heap_inplace_update(pg_db, tuple);
958986
}
959987
table_close(pg_db, RowExclusiveLock);
960988
heap_freetuple(tuple);

0 commit comments

Comments
 (0)