mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Force pg_database updates out to disk immediately after ALTER DATABASE;
this is to avoid scenarios where incoming backends find no live copies of a database's row because the only live copy is in an as-yet-unwritten shared buffer, which they can't see. Also, use FlushRelationBuffers() for forcing out pg_database, instead of the much more expensive BufferSync(). There's no need to write out pages belonging to other relations.
This commit is contained in:
parent
c36496a101
commit
b2a2f4cef7
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.146 2004/10/28 00:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.147 2004/11/18 01:14:26 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -330,7 +330,7 @@ createdb(const CreatedbStmt *stmt)
|
|||||||
/*
|
/*
|
||||||
* Force dirty buffers out to disk, to ensure source database is
|
* Force dirty buffers out to disk, to ensure source database is
|
||||||
* up-to-date for the copy. (We really only need to flush buffers for
|
* up-to-date for the copy. (We really only need to flush buffers for
|
||||||
* the source database...)
|
* the source database, but bufmgr.c provides no API for that.)
|
||||||
*/
|
*/
|
||||||
BufferSync(-1, -1);
|
BufferSync(-1, -1);
|
||||||
|
|
||||||
@ -497,15 +497,15 @@ createdb(const CreatedbStmt *stmt)
|
|||||||
/* Update indexes */
|
/* Update indexes */
|
||||||
CatalogUpdateIndexes(pg_database_rel, tuple);
|
CatalogUpdateIndexes(pg_database_rel, tuple);
|
||||||
|
|
||||||
/* Close pg_database, but keep lock till commit */
|
|
||||||
heap_close(pg_database_rel, NoLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force dirty buffers out to disk, so that newly-connecting backends
|
* Force dirty buffers out to disk, so that newly-connecting backends
|
||||||
* will see the new database in pg_database right away. (They'll see
|
* will see the new database in pg_database right away. (They'll see
|
||||||
* an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
|
* an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
|
||||||
*/
|
*/
|
||||||
BufferSync(-1, -1);
|
FlushRelationBuffers(pg_database_rel, MaxBlockNumber);
|
||||||
|
|
||||||
|
/* Close pg_database, but keep exclusive lock till commit */
|
||||||
|
heap_close(pg_database_rel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -607,12 +607,6 @@ dropdb(const char *dbname)
|
|||||||
*/
|
*/
|
||||||
DeleteComments(db_id, RelationGetRelid(pgdbrel), 0);
|
DeleteComments(db_id, RelationGetRelid(pgdbrel), 0);
|
||||||
|
|
||||||
/*
|
|
||||||
* Close pg_database, but keep exclusive lock till commit to ensure
|
|
||||||
* that any new backend scanning pg_database will see the tuple dead.
|
|
||||||
*/
|
|
||||||
heap_close(pgdbrel, NoLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop pages for this database that are in the shared buffer cache.
|
* Drop pages for this database that are in the shared buffer cache.
|
||||||
* This is important to ensure that no remaining backend tries to
|
* This is important to ensure that no remaining backend tries to
|
||||||
@ -644,7 +638,10 @@ dropdb(const char *dbname)
|
|||||||
* (They'll see an uncommitted deletion, but they don't care; see
|
* (They'll see an uncommitted deletion, but they don't care; see
|
||||||
* GetRawDatabaseInfo.)
|
* GetRawDatabaseInfo.)
|
||||||
*/
|
*/
|
||||||
BufferSync(-1, -1);
|
FlushRelationBuffers(pgdbrel, MaxBlockNumber);
|
||||||
|
|
||||||
|
/* Close pg_database, but keep exclusive lock till commit */
|
||||||
|
heap_close(pgdbrel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -733,7 +730,6 @@ RenameDatabase(const char *oldname, const char *newname)
|
|||||||
CatalogUpdateIndexes(rel, newtup);
|
CatalogUpdateIndexes(rel, newtup);
|
||||||
|
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
heap_close(rel, NoLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force dirty buffers out to disk, so that newly-connecting backends
|
* Force dirty buffers out to disk, so that newly-connecting backends
|
||||||
@ -741,7 +737,10 @@ RenameDatabase(const char *oldname, const char *newname)
|
|||||||
* see an uncommitted tuple, but they don't care; see
|
* see an uncommitted tuple, but they don't care; see
|
||||||
* GetRawDatabaseInfo.)
|
* GetRawDatabaseInfo.)
|
||||||
*/
|
*/
|
||||||
BufferSync(-1, -1);
|
FlushRelationBuffers(rel, MaxBlockNumber);
|
||||||
|
|
||||||
|
/* Close pg_database, but keep exclusive lock till commit */
|
||||||
|
heap_close(rel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -763,7 +762,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
|||||||
|
|
||||||
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
|
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
|
||||||
|
|
||||||
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
|
/*
|
||||||
|
* We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
|
||||||
|
*/
|
||||||
|
rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
|
||||||
ScanKeyInit(&scankey,
|
ScanKeyInit(&scankey,
|
||||||
Anum_pg_database_datname,
|
Anum_pg_database_datname,
|
||||||
BTEqualStrategyNumber, F_NAMEEQ,
|
BTEqualStrategyNumber, F_NAMEEQ,
|
||||||
@ -821,6 +823,16 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
|||||||
CatalogUpdateIndexes(rel, newtuple);
|
CatalogUpdateIndexes(rel, newtuple);
|
||||||
|
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force dirty buffers out to disk, so that newly-connecting backends
|
||||||
|
* will see the altered row in pg_database right away. (They'll
|
||||||
|
* see an uncommitted tuple, but they don't care; see
|
||||||
|
* GetRawDatabaseInfo.)
|
||||||
|
*/
|
||||||
|
FlushRelationBuffers(rel, MaxBlockNumber);
|
||||||
|
|
||||||
|
/* Close pg_database, but keep exclusive lock till commit */
|
||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,7 +849,10 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
|
|||||||
SysScanDesc scan;
|
SysScanDesc scan;
|
||||||
Form_pg_database datForm;
|
Form_pg_database datForm;
|
||||||
|
|
||||||
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
|
/*
|
||||||
|
* We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
|
||||||
|
*/
|
||||||
|
rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
|
||||||
ScanKeyInit(&scankey,
|
ScanKeyInit(&scankey,
|
||||||
Anum_pg_database_datname,
|
Anum_pg_database_datname,
|
||||||
BTEqualStrategyNumber, F_NAMEEQ,
|
BTEqualStrategyNumber, F_NAMEEQ,
|
||||||
@ -901,9 +916,22 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
|
|||||||
CatalogUpdateIndexes(rel, newtuple);
|
CatalogUpdateIndexes(rel, newtuple);
|
||||||
|
|
||||||
heap_freetuple(newtuple);
|
heap_freetuple(newtuple);
|
||||||
}
|
|
||||||
|
|
||||||
|
/* must release buffer pins before FlushRelationBuffers */
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force dirty buffers out to disk, so that newly-connecting backends
|
||||||
|
* will see the altered row in pg_database right away. (They'll
|
||||||
|
* see an uncommitted tuple, but they don't care; see
|
||||||
|
* GetRawDatabaseInfo.)
|
||||||
|
*/
|
||||||
|
FlushRelationBuffers(rel, MaxBlockNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
systable_endscan(scan);
|
||||||
|
|
||||||
|
/* Close pg_database, but keep exclusive lock till commit */
|
||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,7 +1204,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
|
|||||||
/*
|
/*
|
||||||
* Force dirty buffers out to disk, to ensure source database is
|
* Force dirty buffers out to disk, to ensure source database is
|
||||||
* up-to-date for the copy. (We really only need to flush buffers for
|
* up-to-date for the copy. (We really only need to flush buffers for
|
||||||
* the source database...)
|
* the source database, but bufmgr.c provides no API for that.)
|
||||||
*/
|
*/
|
||||||
BufferSync(-1, -1);
|
BufferSync(-1, -1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user