summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeodor Sigaev2015-09-17 11:22:37 +0000
committerTeodor Sigaev2015-09-17 11:22:37 +0000
commit22f519c92a45eb017bf2e65f36506a75309f8094 (patch)
tree822983b85ae1ea823bd2da1d6a3b0f707a554a0f
parent7aea8e4f2daa4b39ca9d1309a0c4aadb0f7ed81b (diff)
Fix bug introduced by microvacuum for GiST
Commit 013ebc0a7b7ea9c1b1ab7a3d4dd75ea121ea8ba7 introduces microvacuum for GiST, deletetion of tuple marked LP_DEAD uses IndexPageMultiDelete while recovery code uses IndexPageTupleDelete in loop. This causes a difference in offset numbers of tuples to delete. Patch introduces usage of IndexPageMultiDelete in GiST except gistplacetopage() where only one tuple is deleted at once. That also slightly improve performance, because IndexPageMultiDelete is more effective. Patch changes WAL format, so bump wal page magic. Bug report from Jeff Janes Diagnostic and patch by Anastasia Lubennikova and me
-rw-r--r--src/backend/access/gist/gist.c5
-rw-r--r--src/backend/access/gist/gistvacuum.c11
-rw-r--r--src/backend/access/gist/gistxlog.c4
-rw-r--r--src/include/access/xlog_internal.h2
4 files changed, 11 insertions, 11 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 4edc5a75f2..53bccf6d18 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -466,6 +466,11 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
*/
START_CRIT_SECTION();
+ /*
+ * While we delete only one tuple at once we could mix calls
+ * PageIndexTupleDelete() here and PageIndexMultiDelete() in
+ * gistRedoPageUpdateRecord()
+ */
if (OffsetNumberIsValid(oldoffnum))
PageIndexTupleDelete(page, oldoffnum);
gistfillbuffer(page, itup, ntup, InvalidOffsetNumber);
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index 2337dbd7f9..a0b0eebed3 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -208,23 +208,20 @@ gistbulkdelete(PG_FUNCTION_ARGS)
idxtuple = (IndexTuple) PageGetItem(page, iid);
if (callback(&(idxtuple->t_tid), callback_state))
- {
- todelete[ntodelete] = i - ntodelete;
- ntodelete++;
- stats->tuples_removed += 1;
- }
+ todelete[ntodelete++] = i;
else
stats->num_index_tuples += 1;
}
+ stats->tuples_removed += ntodelete;
+
if (ntodelete)
{
START_CRIT_SECTION();
MarkBufferDirty(buffer);
- for (i = 0; i < ntodelete; i++)
- PageIndexTupleDelete(page, todelete[i]);
+ PageIndexMultiDelete(page, todelete, ntodelete);
GistMarkTuplesDeleted(page);
if (RelationNeedsWAL(rel))
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index fbdbb3c51f..c63cc8190c 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -83,13 +83,11 @@ gistRedoPageUpdateRecord(XLogReaderState *record)
/* Delete old tuples */
if (xldata->ntodelete > 0)
{
- int i;
OffsetNumber *todelete = (OffsetNumber *) data;
data += sizeof(OffsetNumber) * xldata->ntodelete;
- for (i = 0; i < xldata->ntodelete; i++)
- PageIndexTupleDelete(page, todelete[i]);
+ PageIndexMultiDelete(page, todelete, xldata->ntodelete);
if (GistPageIsLeaf(page))
GistMarkTuplesDeleted(page);
}
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 5ebaa5f69c..590bf1729a 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -31,7 +31,7 @@
/*
* Each page of XLOG file has a header like this:
*/
-#define XLOG_PAGE_MAGIC 0xD085 /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD086 /* can be used as WAL version indicator */
typedef struct XLogPageHeaderData
{