summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistbuild.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2022-02-24 16:15:12 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2022-02-24 16:15:12 +0200
commit6c46e8a5dfc9f49e673d76fc6ae097b81d7740ef (patch)
treefce2433158e4451344fa72b8b7ee0e01febe4706 /src/backend/access/gist/gistbuild.c
parente77216fcb021bb19d83b348db084adfe8d918118 (diff)
downloadpostgresql-6c46e8a5dfc9f49e673d76fc6ae097b81d7740ef.tar.gz
Fix data loss on crash after sorted GiST index build.
If a checkpoint happens during sorted GiST index build, and the system crashes after the checkpoint and after the index build has finished, the data written to the index before the checkpoint started could be lost. The checkpoint won't fsync it, and it won't be replayed at crash recovery either. Fix by calling smgrimmedsync() after the index build, just like in B-tree index build. Backpatch to v14 where the sorted GiST index build was introduced. Reported-by: Melanie Plageman Discussion: https://www.postgresql.org/message-id/CAAKRu_ZJJynimxKj5xYBSziL62-iEtPE+fx-B=JzR=jUtP92mw@mail.gmail.com
Diffstat (limited to 'src/backend/access/gist/gistbuild.c')
-rw-r--r--src/backend/access/gist/gistbuild.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 4db896a533..e081e6571a 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -467,6 +467,18 @@ gist_indexsortbuild(GISTBuildState *state)
pfree(levelstate->pages[0]);
pfree(levelstate);
+
+ /*
+ * When we WAL-logged index pages, we must nonetheless fsync index files.
+ * Since we're building outside shared buffers, a CHECKPOINT occurring
+ * during the build has no way to flush the previously written data to
+ * disk (indeed it won't know the index even exists). A crash later on
+ * would replay WAL from the checkpoint, therefore it wouldn't replay our
+ * earlier WAL entries. If we do not fsync those pages here, they might
+ * still not be on disk when the crash occurs.
+ */
+ if (RelationNeedsWAL(state->indexrel))
+ smgrimmedsync(RelationGetSmgr(state->indexrel), MAIN_FORKNUM);
}
/*