aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/multixact.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2015-07-23 01:30:17 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2015-07-23 01:30:17 +0300
commite54e17aca2f57b4f0ccad3af9d85c3ab12efe668 (patch)
tree7c2d90899bd32d503792262ecc102a8a8a153967 /src/backend/access/transam/multixact.c
parent14ade020ffa805b8335af10a11520b7b2249c99e (diff)
downloadpostgresql-e54e17aca2f57b4f0ccad3af9d85c3ab12efe668.tar.gz
postgresql-e54e17aca2f57b4f0ccad3af9d85c3ab12efe668.zip
Fix off-by-one error in calculating subtrans/multixact truncation point.
If there were no subtransactions (or multixacts) active, we would calculate the oldestxid == next xid. That's correct, but if next XID happens to be on the next pg_subtrans (pg_multixact) page, the page does not exist yet, and SimpleLruTruncate will produce an "apparent wraparound" warning. The warning is harmless in this case, but looks very alarming to users. Backpatch to all supported versions. Patch and analysis by Thomas Munro.
Diffstat (limited to 'src/backend/access/transam/multixact.c')
-rw-r--r--src/backend/access/transam/multixact.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index b90c110dcad..5182b4acb53 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -90,6 +90,8 @@
#define MXOffsetToMemberEntry(xid) \
((xid) % (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
+#define PreviousMultiXactId(xid) \
+ ((xid) == FirstMultiXactId ? MaxMultiXactId : (xid) - 1)
/*
* Links to shared-memory data structures for MultiXact control
@@ -1902,17 +1904,21 @@ TruncateMultiXact(void)
}
/*
- * The cutoff point is the start of the segment containing oldestMXact. We
- * pass the *page* containing oldestMXact to SimpleLruTruncate.
+ * The cutoff point is the start of the segment containing oldestMXact.
+ * We step back one multixact to avoid passing a cutoff page that hasn't
+ * been created yet in the rare case that oldestMXact would be the first
+ * item on a page and oldestMXact == nextMXact. In that case, if we
+ * didn't subtract one, we'd trigger SimpleLruTruncate's wraparound
+ * detection.
*/
- cutoffPage = MultiXactIdToOffsetPage(oldestMXact);
+ cutoffPage = MultiXactIdToOffsetPage(PreviousMultiXactId(oldestMXact));
SimpleLruTruncate(MultiXactOffsetCtl, cutoffPage);
/*
* Also truncate MultiXactMember at the previously determined offset.
*/
- cutoffPage = MXOffsetToMemberPage(oldestOffset);
+ cutoffPage = MXOffsetToMemberPage(oldestOffset - 1);
SimpleLruTruncate(MultiXactMemberCtl, cutoffPage);