Fix_wal_logging_problem_20160311.patch
text/x-patch
Filename: Fix_wal_logging_problem_20160311.patch
Type: text/x-patch
Part: 0
Message:
Re: WAL logging problem in 9.4.3?
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/brin/brin.c | 3 | 2 |
| src/backend/access/gin/gininsert.c | 7 | 4 |
| src/backend/access/gist/gist.c | 6 | 3 |
| src/backend/access/hash/hash.c | 5 | 3 |
| src/backend/access/nbtree/nbtree.c | 9 | 7 |
| src/backend/access/spgist/spginsert.c | 15 | 12 |
| src/backend/catalog/index.c | 15 | 8 |
| src/include/access/amapi.h | 1 | 1 |
| src/include/access/brin_internal.h | 1 | 1 |
| src/include/access/gin_private.h | 1 | 1 |
| src/include/access/gist_private.h | 1 | 1 |
| src/include/access/hash.h | 1 | 1 |
| src/include/access/nbtree.h | 1 | 1 |
| src/include/access/spgist.h | 1 | 1 |
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index c740952..7f0d3f9 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -675,13 +675,14 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
}
void
-brinbuildempty(Relation index)
+brinbuildempty(Relation index, bool persistent)
{
Buffer metabuf;
+ ForkNumber forknum = (persistent ? MAIN_FORKNUM : INIT_FORKNUM);
/* An empty BRIN index has a metapage only. */
metabuf =
- ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
+ ReadBufferExtended(index, forknum, P_NEW, RBM_NORMAL, NULL);
LockBuffer(metabuf, BUFFER_LOCK_EXCLUSIVE);
/* Initialize and xlog metabuffer. */
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index cd21e0e..c041360 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -430,20 +430,23 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
}
/*
- * ginbuildempty() -- build an empty gin index in the initialization fork
+ * ginbuildempty() -- build an empty gin index
+ * the new index is built in the intialization fork or main fork according
+ * to the parameter persistent.
*/
void
-ginbuildempty(Relation index)
+ginbuildempty(Relation index, bool persistent)
{
Buffer RootBuffer,
MetaBuffer;
+ ForkNumber forknum = (persistent ? MAIN_FORKNUM : INIT_FORKNUM);
/* An empty GIN index has two pages. */
MetaBuffer =
- ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
+ ReadBufferExtended(index, forknum, P_NEW, RBM_NORMAL, NULL);
LockBuffer(MetaBuffer, BUFFER_LOCK_EXCLUSIVE);
RootBuffer =
- ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
+ ReadBufferExtended(index, forknum, P_NEW, RBM_NORMAL, NULL);
LockBuffer(RootBuffer, BUFFER_LOCK_EXCLUSIVE);
/* Initialize and xlog metabuffer and root buffer. */
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 996363c..3d73083 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -110,15 +110,18 @@ createTempGistContext(void)
}
/*
- * gistbuildempty() -- build an empty gist index in the initialization fork
+ * gistbuildempty() -- build an empty gist index.
+ * the new index is built in the intialization fork or main fork according
+ * to the parameter persistent.
*/
void
-gistbuildempty(Relation index)
+gistbuildempty(Relation index, bool persistent)
{
Buffer buffer;
+ ForkNumber forknum = (persistent ? MAIN_FORKNUM : INIT_FORKNUM);
/* Initialize the root page */
- buffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
+ buffer = ReadBufferExtended(index, forknum, P_NEW, RBM_NORMAL, NULL);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/* Initialize and xlog buffer */
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 3d48c4f..3b9cd66 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -156,12 +156,14 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
}
/*
- * hashbuildempty() -- build an empty hash index in the initialization fork
+ * hashbuildempty() -- build an empty hash index
+ * the new index is built in the intialization fork or main fork according
+ * to the parameter persistent.
*/
void
-hashbuildempty(Relation index)
+hashbuildempty(Relation index, bool persistent)
{
- _hash_metapinit(index, 0, INIT_FORKNUM);
+ _hash_metapinit(index, 0, persistent ? MAIN_FORKNUM : INIT_FORKNUM);
}
/*
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index f2905cb..c20377d 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -230,12 +230,15 @@ btbuildCallback(Relation index,
}
/*
- * btbuildempty() -- build an empty btree index in the initialization fork
+ * btbuildempty() -- build an empty btree index
+ * the new index is built in the intialization fork or main fork according
+ * to the parameter persistent.
*/
void
-btbuildempty(Relation index)
+btbuildempty(Relation index, bool persistent)
{
Page metapage;
+ ForkNumber forknum = persistent ? MAIN_FORKNUM : INIT_FORKNUM;
/* Construct metapage. */
metapage = (Page) palloc(BLCKSZ);
@@ -243,10 +246,9 @@ btbuildempty(Relation index)
/* Write the page. If archiving/streaming, XLOG it. */
PageSetChecksumInplace(metapage, BTREE_METAPAGE);
- smgrwrite(index->rd_smgr, INIT_FORKNUM, BTREE_METAPAGE,
- (char *) metapage, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ smgrwrite(index->rd_smgr, forknum, BTREE_METAPAGE, (char *) metapage, true);
+ if (XLogIsNeeded() || persistent)
+ log_newpage(&index->rd_smgr->smgr_rnode.node, forknum,
BTREE_METAPAGE, metapage, false);
/*
@@ -254,7 +256,7 @@ btbuildempty(Relation index)
* write did not go through shared_buffers and therefore a concurrent
* checkpoint may have moved the redo pointer past our xlog record.
*/
- smgrimmedsync(index->rd_smgr, INIT_FORKNUM);
+ smgrimmedsync(index->rd_smgr, forknum);
}
/*
diff --git a/src/backend/access/spgist/spginsert.c b/src/backend/access/spgist/spginsert.c
index 44fd644..3d5964b 100644
--- a/src/backend/access/spgist/spginsert.c
+++ b/src/backend/access/spgist/spginsert.c
@@ -152,12 +152,15 @@ spgbuild(Relation heap, Relation index, IndexInfo *indexInfo)
}
/*
- * Build an empty SPGiST index in the initialization fork
+ * Build an empty SPGiST index
+ * the new index is built in the intialization fork or main fork according
+ * to the parameter persistent.
*/
void
-spgbuildempty(Relation index)
+spgbuildempty(Relation index, bool persistent)
{
Page page;
+ ForkNumber forknum = (persistent ? MAIN_FORKNUM : INIT_FORKNUM);
/* Construct metapage. */
page = (Page) palloc(BLCKSZ);
@@ -165,30 +168,30 @@ spgbuildempty(Relation index)
/* Write the page. If archiving/streaming, XLOG it. */
PageSetChecksumInplace(page, SPGIST_METAPAGE_BLKNO);
- smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_METAPAGE_BLKNO,
+ smgrwrite(index->rd_smgr, forknum, SPGIST_METAPAGE_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ if (XLogIsNeeded() || persistent)
+ log_newpage(&index->rd_smgr->smgr_rnode.node, forknum,
SPGIST_METAPAGE_BLKNO, page, false);
/* Likewise for the root page. */
SpGistInitPage(page, SPGIST_LEAF);
PageSetChecksumInplace(page, SPGIST_ROOT_BLKNO);
- smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_ROOT_BLKNO,
+ smgrwrite(index->rd_smgr, forknum, SPGIST_ROOT_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ if (XLogIsNeeded() || persistent)
+ log_newpage(&index->rd_smgr->smgr_rnode.node, forknum,
SPGIST_ROOT_BLKNO, page, true);
/* Likewise for the null-tuples root page. */
SpGistInitPage(page, SPGIST_LEAF | SPGIST_NULLS);
PageSetChecksumInplace(page, SPGIST_NULL_BLKNO);
- smgrwrite(index->rd_smgr, INIT_FORKNUM, SPGIST_NULL_BLKNO,
+ smgrwrite(index->rd_smgr, forknum, SPGIST_NULL_BLKNO,
(char *) page, true);
- if (XLogIsNeeded())
- log_newpage(&index->rd_smgr->smgr_rnode.node, INIT_FORKNUM,
+ if (XLogIsNeeded() || persistent)
+ log_newpage(&index->rd_smgr->smgr_rnode.node, forknum,
SPGIST_NULL_BLKNO, page, true);
/*
@@ -196,7 +199,7 @@ spgbuildempty(Relation index)
* writes did not go through shared buffers and therefore a concurrent
* checkpoint may have moved the redo pointer past our xlog record.
*/
- smgrimmedsync(index->rd_smgr, INIT_FORKNUM);
+ smgrimmedsync(index->rd_smgr, forknum);
}
/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 31a1438..ea8c623 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1987,7 +1987,8 @@ index_build(Relation heapRelation,
bool isprimary,
bool isreindex)
{
- IndexBuildResult *stats;
+ static IndexBuildResult defstats = {0, 0};
+ IndexBuildResult *stats = &defstats;
Oid save_userid;
int save_sec_context;
int save_nestlevel;
@@ -2016,12 +2017,19 @@ index_build(Relation heapRelation,
save_nestlevel = NewGUCNestLevel();
/*
- * Call the access method's build procedure
+ * Call the access method's build procedure. Build an empty index for
+ * empty heaps.
*/
- stats = indexRelation->rd_amroutine->ambuild(heapRelation, indexRelation,
- indexInfo);
- Assert(PointerIsValid(stats));
-
+ if (RelationGetNumberOfBlocks(heapRelation) > 0)
+ stats = indexRelation->rd_amroutine->ambuild(heapRelation,
+ indexRelation,
+ indexInfo);
+ else
+ {
+ RelationOpenSmgr(indexRelation);
+ indexRelation->rd_amroutine->ambuildempty(indexRelation, true);
+ }
+
/*
* If this is an unlogged index, we may need to write out an init fork for
* it -- but we must first check whether one already exists. If, for
@@ -2032,9 +2040,8 @@ index_build(Relation heapRelation,
if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
!smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
{
- RelationOpenSmgr(indexRelation);
smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
- indexRelation->rd_amroutine->ambuildempty(indexRelation);
+ indexRelation->rd_amroutine->ambuildempty(indexRelation, false);
}
/*
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
index 35f1061..220494e 100644
--- a/src/include/access/amapi.h
+++ b/src/include/access/amapi.h
@@ -36,7 +36,7 @@ typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation,
struct IndexInfo *indexInfo);
/* build empty index */
-typedef void (*ambuildempty_function) (Relation indexRelation);
+typedef void (*ambuildempty_function) (Relation indexRelation, bool persistent);
/* insert this tuple */
typedef bool (*aminsert_function) (Relation indexRelation,
diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h
index 47317af..f7e600a 100644
--- a/src/include/access/brin_internal.h
+++ b/src/include/access/brin_internal.h
@@ -86,7 +86,7 @@ extern BrinDesc *brin_build_desc(Relation rel);
extern void brin_free_desc(BrinDesc *bdesc);
extern IndexBuildResult *brinbuild(Relation heap, Relation index,
struct IndexInfo *indexInfo);
-extern void brinbuildempty(Relation index);
+extern void brinbuildempty(Relation index, bool persistent);
extern bool brininsert(Relation idxRel, Datum *values, bool *nulls,
ItemPointer heaptid, Relation heapRel,
IndexUniqueCheck checkUnique);
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index d2ea588..91a2622 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -617,7 +617,7 @@ extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple,
/* gininsert.c */
extern IndexBuildResult *ginbuild(Relation heap, Relation index,
struct IndexInfo *indexInfo);
-extern void ginbuildempty(Relation index);
+extern void ginbuildempty(Relation index, bool persistent);
extern bool gininsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique);
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index f9732ba..448044e 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -428,7 +428,7 @@ typedef struct GiSTOptions
/* gist.c */
extern Datum gisthandler(PG_FUNCTION_ARGS);
-extern void gistbuildempty(Relation index);
+extern void gistbuildempty(Relation index, bool persistent);
extern bool gistinsert(Relation r, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique);
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 3a68390..ab93e34 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -246,7 +246,7 @@ typedef HashMetaPageData *HashMetaPage;
extern Datum hashhandler(PG_FUNCTION_ARGS);
extern IndexBuildResult *hashbuild(Relation heap, Relation index,
struct IndexInfo *indexInfo);
-extern void hashbuildempty(Relation index);
+extern void hashbuildempty(Relation index, bool persistent);
extern bool hashinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique);
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 9046b16..64de387 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -656,7 +656,7 @@ typedef BTScanOpaqueData *BTScanOpaque;
extern Datum bthandler(PG_FUNCTION_ARGS);
extern IndexBuildResult *btbuild(Relation heap, Relation index,
struct IndexInfo *indexInfo);
-extern void btbuildempty(Relation index);
+extern void btbuildempty(Relation index, bool persistent);
extern bool btinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique);
diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h
index 1994f71..3c26cde 100644
--- a/src/include/access/spgist.h
+++ b/src/include/access/spgist.h
@@ -181,7 +181,7 @@ extern bytea *spgoptions(Datum reloptions, bool validate);
/* spginsert.c */
extern IndexBuildResult *spgbuild(Relation heap, Relation index,
struct IndexInfo *indexInfo);
-extern void spgbuildempty(Relation index);
+extern void spgbuildempty(Relation index, bool persistent);
extern bool spginsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique);