Skip to content
Snippets Groups Projects
Commit b2a2f4ce authored by Tom Lane's avatar Tom Lane
Browse files

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.
parent c36496a1
No related branches found
No related tags found
No related merge requests found
...@@ -9,7 +9,7 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment