Re: WAL logging problem in 9.4.3?

Поиск
Список
Период
Сортировка
От Kyotaro HORIGUCHI
Тема Re: WAL logging problem in 9.4.3?
Дата
Msg-id 20160311.173259.190313590.horiguchi.kyotaro@lab.ntt.co.jp
обсуждение исходный текст
Ответ на Re: WAL logging problem in 9.4.3?  (Michael Paquier <michael.paquier@gmail.com>)
Ответы Re: WAL logging problem in 9.4.3?  (Michael Paquier <michael.paquier@gmail.com>)
Список pgsql-hackers
Hello, I considered on the original issue.

At Fri, 19 Feb 2016 22:27:00 +0900, Michael Paquier <michael.paquier@gmail.com> wrote in
<CAB7nPqSGFKUAFqPe5t30jeEA+V9yFMM4yJGa3SnkgY1RHzn7Dg@mail.gmail.com>
> > Worth noting that this patch does not address the problem with index
> > relations when a TRUNCATE is used in the same transaction as its

Focusing this issue, what we should do is somehow building empty
index just after a index truncation. The attached patch does the
following things to fix this.

- make index_build use ambuildempty when the relation on which the index will be built is apparently empty. That is,
whenthe relation has no block.
 

- add one parameter "persistent" to ambuildempty(). It behaves as before if the parameter is false. If not, it creates
anempty index on MAIN_FORK and emits logs even if wal_level is minimal.
 

Creation of an index for an empty table can be safely done by
ambuildempty, since it creates the image for init fork, which can
be simply copied as main fork on initialization. And the heap is
always empty when RelationTruncateIndexes calls index_build.

For nonempty tables, ambuild properly initializes the new index.

The new parameter 'persistent' would be better be forknum because
it actually represents the persistency of the index to be
created. But I'm out of time now..


regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
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
checkwhether 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(Relationheap, 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); 

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Craig Ringer
Дата:
Сообщение: Re: The plan for FDW-based sharding
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: The plan for FDW-based sharding