Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd493bed

Browse files
committed
Handle interleavings between CREATE DATABASE steps and base backup.
Restoring a base backup taken in the middle of CreateDirAndVersionFile()or write_relmap_file() would lose the function's effects. The symptomwas absence of the database directory, PG_VERSION file, orpg_filenode.map. If missing the directory, recovery would fail. Eithermissing file would not fail recovery but would render the new databaseunusable. Fix CreateDirAndVersionFile() with the transam/README "actionfirst and then write a WAL entry" strategy. That has a side benefit ofmoving filesystem mutations out of a critical section, reducing the waysto PANIC. Fix the write_relmap_file() call with a lock acquisition, soit interacts with checkpoints like non-CREATE DATABASE calls do.Back-patch to v15, where commit9c08aeaintroduced STRATEGY=WAL_LOG and made it the default.Discussion:https://postgr.es/m/20240130195003.0a.nmisch@google.com
1 parent970b1ae commitd493bed

File tree

2 files changed

+32
-28
lines changed

2 files changed

+32
-28
lines changed

‎src/backend/commands/dbcommands.c

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -461,35 +461,12 @@ CreateDirAndVersionFile(char *dbpath, Oid dbid, Oid tsid, bool isRedo)
461461
charbuf[16];
462462

463463
/*
464-
* Prepare version data before starting a critical section.
465-
*
466-
* Note that we don't have to copy this from the source database; there's
467-
* only one legal value.
464+
* Note that we don't have to copy version data from the source database;
465+
* there's only one legal value.
468466
*/
469467
sprintf(buf,"%s\n",PG_MAJORVERSION);
470468
nbytes=strlen(PG_MAJORVERSION)+1;
471469

472-
/* If we are not in WAL replay then write the WAL. */
473-
if (!isRedo)
474-
{
475-
xl_dbase_create_wal_log_recxlrec;
476-
XLogRecPtrlsn;
477-
478-
START_CRIT_SECTION();
479-
480-
xlrec.db_id=dbid;
481-
xlrec.tablespace_id=tsid;
482-
483-
XLogBeginInsert();
484-
XLogRegisterData((char*) (&xlrec),
485-
sizeof(xl_dbase_create_wal_log_rec));
486-
487-
lsn=XLogInsert(RM_DBASE_ID,XLOG_DBASE_CREATE_WAL_LOG);
488-
489-
/* As always, WAL must hit the disk before the data update does. */
490-
XLogFlush(lsn);
491-
}
492-
493470
/* Create database directory. */
494471
if (MakePGDirectory(dbpath)<0)
495472
{
@@ -533,9 +510,24 @@ CreateDirAndVersionFile(char *dbpath, Oid dbid, Oid tsid, bool isRedo)
533510
/* Close the version file. */
534511
CloseTransientFile(fd);
535512

536-
/*Critical section done. */
513+
/*If we are not in WAL replay then write the WAL. */
537514
if (!isRedo)
515+
{
516+
xl_dbase_create_wal_log_recxlrec;
517+
518+
START_CRIT_SECTION();
519+
520+
xlrec.db_id=dbid;
521+
xlrec.tablespace_id=tsid;
522+
523+
XLogBeginInsert();
524+
XLogRegisterData((char*) (&xlrec),
525+
sizeof(xl_dbase_create_wal_log_rec));
526+
527+
(void)XLogInsert(RM_DBASE_ID,XLOG_DBASE_CREATE_WAL_LOG);
528+
538529
END_CRIT_SECTION();
530+
}
539531
}
540532

541533
/*

‎src/backend/utils/cache/relmapper.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,15 @@ RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath)
298298
* Write the same data into the destination database's relmap file.
299299
*
300300
* No sinval is needed because no one can be connected to the destination
301-
* database yet. For the same reason, there is no need to acquire
302-
* RelationMappingLock.
301+
* database yet.
303302
*
304303
* There's no point in trying to preserve files here. The new database
305304
* isn't usable yet anyway, and won't ever be if we can't install a relmap
306305
* file.
307306
*/
307+
LWLockAcquire(RelationMappingLock,LW_EXCLUSIVE);
308308
write_relmap_file(&map, true, false, false,dbid,tsid,dstdbpath);
309+
LWLockRelease(RelationMappingLock);
309310
}
310311

311312
/*
@@ -627,10 +628,12 @@ RelationMapFinishBootstrap(void)
627628
Assert(pending_local_updates.num_mappings==0);
628629

629630
/* Write the files; no WAL or sinval needed */
631+
LWLockAcquire(RelationMappingLock,LW_EXCLUSIVE);
630632
write_relmap_file(&shared_map, false, false, false,
631633
InvalidOid,GLOBALTABLESPACE_OID,"global");
632634
write_relmap_file(&local_map, false, false, false,
633635
MyDatabaseId,MyDatabaseTableSpace,DatabasePath);
636+
LWLockRelease(RelationMappingLock);
634637
}
635638

636639
/*
@@ -876,6 +879,15 @@ write_relmap_file(RelMapFile *newmap, bool write_wal, bool send_sinval,
876879
intfd;
877880
charmapfilename[MAXPGPATH];
878881

882+
/*
883+
* Even without concurrent use of this map, CheckPointRelationMap() relies
884+
* on this locking. Without it, a restore of a base backup taken after
885+
* this function's XLogInsert() and before its durable_rename() would not
886+
* have the changes. wal_level=minimal doesn't need the lock, but this
887+
* isn't performance-critical enough for such a micro-optimization.
888+
*/
889+
Assert(LWLockHeldByMeInMode(RelationMappingLock,LW_EXCLUSIVE));
890+
879891
/*
880892
* Fill in the overhead fields and update CRC.
881893
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp