33 * dbcommands.c
44 *Database management commands (create/drop database).
55 *
6+ * Note: database creation/destruction commands take ExclusiveLock on
7+ * pg_database to ensure that no two proceed in parallel. We must use
8+ * at least this level of locking to ensure that no two backends try to
9+ * write the flat-file copy of pg_database at once. We avoid using
10+ * AccessExclusiveLock since there's no need to lock out ordinary readers
11+ * of pg_database.
612 *
713 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
814 * Portions Copyright (c) 1994, Regents of the University of California
915 *
1016 *
1117 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.150 2005/02/20 02:21:34 tgl Exp $
18+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.151 2005/02/26 18:43:33 tgl Exp $
1319 *
1420 *-------------------------------------------------------------------------
1521 */
@@ -446,13 +452,13 @@ createdb(const CreatedbStmt *stmt)
446452/*
447453 * Now OK to grab exclusive lock on pg_database.
448454 */
449- pg_database_rel = heap_openr (DatabaseRelationName ,AccessExclusiveLock );
455+ pg_database_rel = heap_openr (DatabaseRelationName ,ExclusiveLock );
450456
451457/* Check to see if someone else created same DB name meanwhile. */
452458if (get_db_info (dbname ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ,NULL ))
453459{
454460/* Don't hold lock while doing recursive remove */
455- heap_close (pg_database_rel ,AccessExclusiveLock );
461+ heap_close (pg_database_rel ,ExclusiveLock );
456462remove_dbtablespaces (dboid );
457463ereport (ERROR ,
458464(errcode (ERRCODE_DUPLICATE_DATABASE ),
@@ -498,13 +504,6 @@ createdb(const CreatedbStmt *stmt)
498504/* Update indexes */
499505CatalogUpdateIndexes (pg_database_rel ,tuple );
500506
501- /*
502- * Force dirty buffers out to disk, so that newly-connecting backends
503- * will see the new database in pg_database right away. (They'll see
504- * an uncommitted tuple, but they don't care; see GetRawDatabaseInfo.)
505- */
506- FlushRelationBuffers (pg_database_rel ,MaxBlockNumber );
507-
508507/* Close pg_database, but keep exclusive lock till commit */
509508heap_close (pg_database_rel ,NoLock );
510509
@@ -542,12 +541,15 @@ dropdb(const char *dbname)
542541 * Obtain exclusive lock on pg_database. We need this to ensure that
543542 * no new backend starts up in the target database while we are
544543 * deleting it. (Actually, a new backend might still manage to start
545- * up, because it will read pg_database without any locking to
546- * discover the database's OID. But it will detect its error in
547- * ReverifyMyDatabase and shut down before any serious damage is done.
548- * See postinit.c.)
544+ * up, because it isn't able to lock pg_database while starting. But
545+ * it will detect its error in ReverifyMyDatabase and shut down before
546+ * any serious damage is done. See postinit.c.)
547+ *
548+ * An ExclusiveLock, rather than AccessExclusiveLock, is sufficient
549+ * since ReverifyMyDatabase takes RowShareLock. This allows ordinary
550+ * readers of pg_database to proceed in parallel.
549551 */
550- pgdbrel = heap_openr (DatabaseRelationName ,AccessExclusiveLock );
552+ pgdbrel = heap_openr (DatabaseRelationName ,ExclusiveLock );
551553
552554if (!get_db_info (dbname ,& db_id ,& db_owner ,NULL ,
553555& db_istemplate ,NULL ,NULL ,NULL ,NULL ))
@@ -638,14 +640,6 @@ dropdb(const char *dbname)
638640 */
639641remove_dbtablespaces (db_id );
640642
641- /*
642- * Force dirty buffers out to disk, so that newly-connecting backends
643- * will see the database tuple marked dead in pg_database right away.
644- * (They'll see an uncommitted deletion, but they don't care; see
645- * GetRawDatabaseInfo.)
646- */
647- FlushRelationBuffers (pgdbrel ,MaxBlockNumber );
648-
649643/* Close pg_database, but keep exclusive lock till commit */
650644heap_close (pgdbrel ,NoLock );
651645
@@ -671,10 +665,10 @@ RenameDatabase(const char *oldname, const char *newname)
671665key2 ;
672666
673667/*
674- * ObtainAccessExclusiveLock so that no new session gets started
668+ * ObtainExclusiveLock so that no new session gets started
675669 * while the rename is in progress.
676670 */
677- rel = heap_openr (DatabaseRelationName ,AccessExclusiveLock );
671+ rel = heap_openr (DatabaseRelationName ,ExclusiveLock );
678672
679673ScanKeyInit (& key ,
680674Anum_pg_database_datname ,
@@ -742,14 +736,6 @@ RenameDatabase(const char *oldname, const char *newname)
742736
743737systable_endscan (scan );
744738
745- /*
746- * Force dirty buffers out to disk, so that newly-connecting backends
747- * will see the renamed database in pg_database right away. (They'll
748- * see an uncommitted tuple, but they don't care; see
749- * GetRawDatabaseInfo.)
750- */
751- FlushRelationBuffers (rel ,MaxBlockNumber );
752-
753739/* Close pg_database, but keep exclusive lock till commit */
754740heap_close (rel ,NoLock );
755741
@@ -779,9 +765,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
779765valuestr = flatten_set_variable_args (stmt -> variable ,stmt -> value );
780766
781767/*
782- * We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
768+ * We don't need ExclusiveLock since we aren't updating the
769+ * flat file.
783770 */
784- rel = heap_openr (DatabaseRelationName ,AccessExclusiveLock );
771+ rel = heap_openr (DatabaseRelationName ,RowExclusiveLock );
785772ScanKeyInit (& scankey ,
786773Anum_pg_database_datname ,
787774BTEqualStrategyNumber ,F_NAMEEQ ,
@@ -840,15 +827,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
840827
841828systable_endscan (scan );
842829
843- /*
844- * Force dirty buffers out to disk, so that newly-connecting backends
845- * will see the altered row in pg_database right away. (They'll
846- * see an uncommitted tuple, but they don't care; see
847- * GetRawDatabaseInfo.)
848- */
849- FlushRelationBuffers (rel ,MaxBlockNumber );
850-
851- /* Close pg_database, but keep exclusive lock till commit */
830+ /* Close pg_database, but keep lock till commit */
852831heap_close (rel ,NoLock );
853832
854833/*
@@ -871,9 +850,10 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
871850Form_pg_database datForm ;
872851
873852/*
874- * We need AccessExclusiveLock so we can safely do FlushRelationBuffers.
853+ * We don't need ExclusiveLock since we aren't updating the
854+ * flat file.
875855 */
876- rel = heap_openr (DatabaseRelationName ,AccessExclusiveLock );
856+ rel = heap_openr (DatabaseRelationName ,RowExclusiveLock );
877857ScanKeyInit (& scankey ,
878858Anum_pg_database_datname ,
879859BTEqualStrategyNumber ,F_NAMEEQ ,
@@ -937,22 +917,11 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
937917CatalogUpdateIndexes (rel ,newtuple );
938918
939919heap_freetuple (newtuple );
940-
941- /* must release buffer pins before FlushRelationBuffers */
942- systable_endscan (scan );
943-
944- /*
945- * Force dirty buffers out to disk, so that newly-connecting backends
946- * will see the altered row in pg_database right away. (They'll
947- * see an uncommitted tuple, but they don't care; see
948- * GetRawDatabaseInfo.)
949- */
950- FlushRelationBuffers (rel ,MaxBlockNumber );
951920}
952- else
953- systable_endscan (scan );
954921
955- /* Close pg_database, but keep exclusive lock till commit */
922+ systable_endscan (scan );
923+
924+ /* Close pg_database, but keep lock till commit */
956925heap_close (rel ,NoLock );
957926
958927/*