diff options
| author | Alexander Korotkov | 2024-02-11 22:33:44 +0000 |
|---|---|---|
| committer | Alexander Korotkov | 2024-02-11 22:52:25 +0000 |
| commit | 8be93177c46b0f6a29a7376229b7ee002066d5f8 (patch) | |
| tree | 1f74eb92722f4c9dbc84dc103f9fb38591f0f950 | |
| parent | 428e2de1b895079bbf50a128f8b3824679f4bb65 (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.c | 36 |
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); |
