Skip to content

Commit b2a2f4c

Browse files
committed
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.
1 parent c36496a commit b2a2f4c

File tree

1 file changed

+47
-19
lines changed

1 file changed

+47
-19
lines changed

src/backend/commands/dbcommands.c

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.146 2004/10/28 00:39:58 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.147 2004/11/18 01:14:26 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -330,7 +330,7 @@ createdb(const CreatedbStmt *stmt)
330330
/*
331331
* Force dirty buffers out to disk, to ensure source database is
332332
* up-to-date for the copy. (We really only need to flush buffers for
333-
* the source database...)
333+
* the source database, but bufmgr.c provides no API for that.)
334334
*/
335335
BufferSync(-1, -1);
336336

@@ -497,15 +497,15 @@ createdb(const CreatedbStmt *stmt)
497497
/* Update indexes */
498498
CatalogUpdateIndexes(pg_database_rel, tuple);
499499

500-
/* Close pg_database, but keep lock till commit */
501-
heap_close(pg_database_rel, NoLock);
502-
503500
/*
504501
* Force dirty buffers out to disk, so that newly-connecting backends
505502
* will see the new database in pg_database right away. (They'll see
506503
* an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
507504
*/
508-
BufferSync(-1, -1);
505+
FlushRelationBuffers(pg_database_rel, MaxBlockNumber);
506+
507+
/* Close pg_database, but keep exclusive lock till commit */
508+
heap_close(pg_database_rel, NoLock);
509509
}
510510

511511

@@ -607,12 +607,6 @@ dropdb(const char *dbname)
607607
*/
608608
DeleteComments(db_id, RelationGetRelid(pgdbrel), 0);
609609

610-
/*
611-
* Close pg_database, but keep exclusive lock till commit to ensure
612-
* that any new backend scanning pg_database will see the tuple dead.
613-
*/
614-
heap_close(pgdbrel, NoLock);
615-
616610
/*
617611
* Drop pages for this database that are in the shared buffer cache.
618612
* This is important to ensure that no remaining backend tries to
@@ -644,7 +638,10 @@ dropdb(const char *dbname)
644638
* (They'll see an uncommitted deletion, but they don't care; see
645639
* GetRawDatabaseInfo.)
646640
*/
647-
BufferSync(-1, -1);
641+
FlushRelationBuffers(pgdbrel, MaxBlockNumber);
642+
643+
/* Close pg_database, but keep exclusive lock till commit */
644+
heap_close(pgdbrel, NoLock);
648645
}
649646

650647

@@ -733,15 +730,17 @@ RenameDatabase(const char *oldname, const char *newname)
733730
CatalogUpdateIndexes(rel, newtup);
734731

735732
systable_endscan(scan);
736-
heap_close(rel, NoLock);
737733

738734
/*
739735
* Force dirty buffers out to disk, so that newly-connecting backends
740736
* will see the renamed database in pg_database right away. (They'll
741737
* see an uncommitted tuple, but they don't care; see
742738
* GetRawDatabaseInfo.)
743739
*/
744-
BufferSync(-1, -1);
740+
FlushRelationBuffers(rel, MaxBlockNumber);
741+
742+
/* Close pg_database, but keep exclusive lock till commit */
743+
heap_close(rel, NoLock);
745744
}
746745

747746

@@ -763,7 +762,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
763762

764763
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
765764

766-
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
765+
/*
766+
* We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
767+
*/
768+
rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
767769
ScanKeyInit(&scankey,
768770
Anum_pg_database_datname,
769771
BTEqualStrategyNumber, F_NAMEEQ,
@@ -821,6 +823,16 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
821823
CatalogUpdateIndexes(rel, newtuple);
822824

823825
systable_endscan(scan);
826+
827+
/*
828+
* Force dirty buffers out to disk, so that newly-connecting backends
829+
* will see the altered row in pg_database right away. (They'll
830+
* see an uncommitted tuple, but they don't care; see
831+
* GetRawDatabaseInfo.)
832+
*/
833+
FlushRelationBuffers(rel, MaxBlockNumber);
834+
835+
/* Close pg_database, but keep exclusive lock till commit */
824836
heap_close(rel, NoLock);
825837
}
826838

@@ -837,7 +849,10 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
837849
SysScanDesc scan;
838850
Form_pg_database datForm;
839851

840-
rel = heap_openr(DatabaseRelationName, RowExclusiveLock);
852+
/*
853+
* We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
854+
*/
855+
rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
841856
ScanKeyInit(&scankey,
842857
Anum_pg_database_datname,
843858
BTEqualStrategyNumber, F_NAMEEQ,
@@ -901,9 +916,22 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
901916
CatalogUpdateIndexes(rel, newtuple);
902917

903918
heap_freetuple(newtuple);
919+
920+
/* must release buffer pins before FlushRelationBuffers */
921+
systable_endscan(scan);
922+
923+
/*
924+
* Force dirty buffers out to disk, so that newly-connecting backends
925+
* will see the altered row in pg_database right away. (They'll
926+
* see an uncommitted tuple, but they don't care; see
927+
* GetRawDatabaseInfo.)
928+
*/
929+
FlushRelationBuffers(rel, MaxBlockNumber);
904930
}
931+
else
932+
systable_endscan(scan);
905933

906-
systable_endscan(scan);
934+
/* Close pg_database, but keep exclusive lock till commit */
907935
heap_close(rel, NoLock);
908936
}
909937

@@ -1176,7 +1204,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
11761204
/*
11771205
* Force dirty buffers out to disk, to ensure source database is
11781206
* up-to-date for the copy. (We really only need to flush buffers for
1179-
* the source database...)
1207+
* the source database, but bufmgr.c provides no API for that.)
11801208
*/
11811209
BufferSync(-1, -1);
11821210

0 commit comments

Comments
 (0)