mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
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
This commit is contained in:
@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "access/heapam.h"
|
||||||
#include "access/htup_details.h"
|
#include "access/htup_details.h"
|
||||||
#include "access/table.h"
|
#include "access/table.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
@ -943,18 +944,45 @@ EventTriggerOnLogin(void)
|
|||||||
Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
|
Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
Form_pg_database db;
|
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))
|
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);
|
db = (Form_pg_database) GETSTRUCT(tuple);
|
||||||
if (db->dathasloginevt)
|
if (db->dathasloginevt)
|
||||||
{
|
{
|
||||||
db->dathasloginevt = false;
|
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);
|
table_close(pg_db, RowExclusiveLock);
|
||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
|
Reference in New Issue
Block a user