Skip to content

Commit 78a572b

Browse files
committed
When cloning template0 (or other fully-frozen databases), set the new
database's datallowconn and datfrozenxid to the current transaction ID instead of copying the source database's values. This is OK because we assume the source DB contains no normal transaction IDs whatsoever. This keeps VACUUM from immediately starting to complain about unvacuumed databases in the situation where we are more than 2 billion transactions out from the XID stamp of template0. Per discussion with Milen Radev (although his complaint turned out to be due to something else, but the problem is real anyway).
1 parent c7bbe99 commit 78a572b

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

src/backend/commands/dbcommands.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.153 2005/03/12 21:11:50 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.154 2005/03/12 21:33:55 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -54,7 +54,8 @@
5454

5555
/* non-export function prototypes */
5656
static bool get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
57-
int *encodingP, bool *dbIsTemplateP, Oid *dbLastSysOidP,
57+
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
58+
Oid *dbLastSysOidP,
5859
TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP,
5960
Oid *dbTablespace);
6061
static bool have_createdb_privilege(void);
@@ -73,6 +74,7 @@ createdb(const CreatedbStmt *stmt)
7374
AclId src_owner;
7475
int src_encoding;
7576
bool src_istemplate;
77+
bool src_allowconn;
7678
Oid src_lastsysoid;
7779
TransactionId src_vacuumxid;
7880
TransactionId src_frozenxid;
@@ -217,7 +219,8 @@ createdb(const CreatedbStmt *stmt)
217219
* idea, so accept possibility of race to create. We will check again
218220
* after we grab the exclusive lock.
219221
*/
220-
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
222+
if (get_db_info(dbname, NULL, NULL, NULL,
223+
NULL, NULL, NULL, NULL, NULL, NULL))
221224
ereport(ERROR,
222225
(errcode(ERRCODE_DUPLICATE_DATABASE),
223226
errmsg("database \"%s\" already exists", dbname)));
@@ -229,7 +232,7 @@ createdb(const CreatedbStmt *stmt)
229232
dbtemplate = "template1"; /* Default template database name */
230233

231234
if (!get_db_info(dbtemplate, &src_dboid, &src_owner, &src_encoding,
232-
&src_istemplate, &src_lastsysoid,
235+
&src_istemplate, &src_allowconn, &src_lastsysoid,
233236
&src_vacuumxid, &src_frozenxid, &src_deftablespace))
234237
ereport(ERROR,
235238
(errcode(ERRCODE_UNDEFINED_DATABASE),
@@ -328,6 +331,16 @@ createdb(const CreatedbStmt *stmt)
328331
/* Note there is no additional permission check in this path */
329332
}
330333

334+
/*
335+
* Normally we mark the new database with the same datvacuumxid and
336+
* datfrozenxid as the source. However, if the source is not allowing
337+
* connections then we assume it is fully frozen, and we can set the
338+
* current transaction ID as the xid limits. This avoids immediately
339+
* starting to generate warnings after cloning template0.
340+
*/
341+
if (!src_allowconn)
342+
src_vacuumxid = src_frozenxid = GetCurrentTransactionId();
343+
331344
/*
332345
* Preassign OID for pg_database tuple, so that we can compute db
333346
* path.
@@ -455,7 +468,8 @@ createdb(const CreatedbStmt *stmt)
455468
pg_database_rel = heap_openr(DatabaseRelationName, ExclusiveLock);
456469

457470
/* Check to see if someone else created same DB name meanwhile. */
458-
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
471+
if (get_db_info(dbname, NULL, NULL, NULL,
472+
NULL, NULL, NULL, NULL, NULL, NULL))
459473
{
460474
/* Don't hold lock while doing recursive remove */
461475
heap_close(pg_database_rel, ExclusiveLock);
@@ -552,7 +566,7 @@ dropdb(const char *dbname)
552566
pgdbrel = heap_openr(DatabaseRelationName, ExclusiveLock);
553567

554568
if (!get_db_info(dbname, &db_id, &db_owner, NULL,
555-
&db_istemplate, NULL, NULL, NULL, NULL))
569+
&db_istemplate, NULL, NULL, NULL, NULL, NULL))
556570
ereport(ERROR,
557571
(errcode(ERRCODE_UNDEFINED_DATABASE),
558572
errmsg("database \"%s\" does not exist", dbname)));
@@ -936,7 +950,8 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
936950

937951
static bool
938952
get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
939-
int *encodingP, bool *dbIsTemplateP, Oid *dbLastSysOidP,
953+
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
954+
Oid *dbLastSysOidP,
940955
TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP,
941956
Oid *dbTablespace)
942957
{
@@ -978,6 +993,9 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
978993
/* allowed as template? */
979994
if (dbIsTemplateP)
980995
*dbIsTemplateP = dbform->datistemplate;
996+
/* allowing connections? */
997+
if (dbAllowConnP)
998+
*dbAllowConnP = dbform->datallowconn;
981999
/* last system OID used in database */
9821000
if (dbLastSysOidP)
9831001
*dbLastSysOidP = dbform->datlastsysoid;

0 commit comments

Comments
 (0)