3
3
* dbcommands.c
4
4
* Database management commands (create/drop database).
5
5
*
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.
6
12
*
7
13
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
8
14
* Portions Copyright (c) 1994, Regents of the University of California
9
15
*
10
16
*
11
17
* 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 $
13
19
*
14
20
*-------------------------------------------------------------------------
15
21
*/
@@ -446,13 +452,13 @@ createdb(const CreatedbStmt *stmt)
446
452
/*
447
453
* Now OK to grab exclusive lock on pg_database.
448
454
*/
449
- pg_database_rel = heap_openr (DatabaseRelationName , AccessExclusiveLock );
455
+ pg_database_rel = heap_openr (DatabaseRelationName , ExclusiveLock );
450
456
451
457
/* Check to see if someone else created same DB name meanwhile. */
452
458
if (get_db_info (dbname , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ))
453
459
{
454
460
/* Don't hold lock while doing recursive remove */
455
- heap_close (pg_database_rel , AccessExclusiveLock );
461
+ heap_close (pg_database_rel , ExclusiveLock );
456
462
remove_dbtablespaces (dboid );
457
463
ereport (ERROR ,
458
464
(errcode (ERRCODE_DUPLICATE_DATABASE ),
@@ -498,13 +504,6 @@ createdb(const CreatedbStmt *stmt)
498
504
/* Update indexes */
499
505
CatalogUpdateIndexes (pg_database_rel , tuple );
500
506
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
-
508
507
/* Close pg_database, but keep exclusive lock till commit */
509
508
heap_close (pg_database_rel , NoLock );
510
509
@@ -542,12 +541,15 @@ dropdb(const char *dbname)
542
541
* Obtain exclusive lock on pg_database. We need this to ensure that
543
542
* no new backend starts up in the target database while we are
544
543
* 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.
549
551
*/
550
- pgdbrel = heap_openr (DatabaseRelationName , AccessExclusiveLock );
552
+ pgdbrel = heap_openr (DatabaseRelationName , ExclusiveLock );
551
553
552
554
if (!get_db_info (dbname , & db_id , & db_owner , NULL ,
553
555
& db_istemplate , NULL , NULL , NULL , NULL ))
@@ -638,14 +640,6 @@ dropdb(const char *dbname)
638
640
*/
639
641
remove_dbtablespaces (db_id );
640
642
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
-
649
643
/* Close pg_database, but keep exclusive lock till commit */
650
644
heap_close (pgdbrel , NoLock );
651
645
@@ -671,10 +665,10 @@ RenameDatabase(const char *oldname, const char *newname)
671
665
key2 ;
672
666
673
667
/*
674
- * Obtain AccessExclusiveLock so that no new session gets started
668
+ * Obtain ExclusiveLock so that no new session gets started
675
669
* while the rename is in progress.
676
670
*/
677
- rel = heap_openr (DatabaseRelationName , AccessExclusiveLock );
671
+ rel = heap_openr (DatabaseRelationName , ExclusiveLock );
678
672
679
673
ScanKeyInit (& key ,
680
674
Anum_pg_database_datname ,
@@ -742,14 +736,6 @@ RenameDatabase(const char *oldname, const char *newname)
742
736
743
737
systable_endscan (scan );
744
738
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
-
753
739
/* Close pg_database, but keep exclusive lock till commit */
754
740
heap_close (rel , NoLock );
755
741
@@ -779,9 +765,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
779
765
valuestr = flatten_set_variable_args (stmt -> variable , stmt -> value );
780
766
781
767
/*
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.
783
770
*/
784
- rel = heap_openr (DatabaseRelationName , AccessExclusiveLock );
771
+ rel = heap_openr (DatabaseRelationName , RowExclusiveLock );
785
772
ScanKeyInit (& scankey ,
786
773
Anum_pg_database_datname ,
787
774
BTEqualStrategyNumber , F_NAMEEQ ,
@@ -840,15 +827,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
840
827
841
828
systable_endscan (scan );
842
829
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 */
852
831
heap_close (rel , NoLock );
853
832
854
833
/*
@@ -871,9 +850,10 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
871
850
Form_pg_database datForm ;
872
851
873
852
/*
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.
875
855
*/
876
- rel = heap_openr (DatabaseRelationName , AccessExclusiveLock );
856
+ rel = heap_openr (DatabaseRelationName , RowExclusiveLock );
877
857
ScanKeyInit (& scankey ,
878
858
Anum_pg_database_datname ,
879
859
BTEqualStrategyNumber , F_NAMEEQ ,
@@ -937,22 +917,11 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
937
917
CatalogUpdateIndexes (rel , newtuple );
938
918
939
919
heap_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 );
951
920
}
952
- else
953
- systable_endscan (scan );
954
921
955
- /* Close pg_database, but keep exclusive lock till commit */
922
+ systable_endscan (scan );
923
+
924
+ /* Close pg_database, but keep lock till commit */
956
925
heap_close (rel , NoLock );
957
926
958
927
/*
0 commit comments