From 8eace46d34ab6ac0d887aa4d3504bc4222c2e448 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Thu, 19 Jan 2017 18:23:09 -0300 Subject: Fix race condition in reading commit timestamps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a user requests the commit timestamp for a transaction old enough that its data is concurrently being truncated away by vacuum at just the right time, they would receive an ugly internal file-not-found error message from slru.c rather than the expected NULL return value. In a primary server, the window for the race is very small: the lookup has to occur exactly between the two calls by vacuum, and there's not a lot that happens between them (mostly just a multixact truncate). In a standby server, however, the window is larger because the truncation is executed as soon as the WAL record for it is replayed, but the advance of the oldest-Xid is not executed until the next checkpoint record. To fix in the primary, simply reverse the order of operations in vac_truncate_clog. To fix in the standby, augment the WAL truncation record so that the standby is aware of the new oldest-XID value and can apply the update immediately. WAL version bumped because of this. No backpatch, because of the low importance of the bug and its rarity. Author: Craig Ringer Reviewed-By: Petr JelĂ­nek, Peter Eisentraut Discussion: https://postgr.es/m/CAMsr+YFhVtRQT1VAwC+WGbbxZZRzNou=N9Ed-FrCqkwQ8H8oJQ@mail.gmail.com --- src/include/access/commit_ts.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/include/access/commit_ts.h') diff --git a/src/include/access/commit_ts.h b/src/include/access/commit_ts.h index 98bd938d5be..f172c91d8f3 100644 --- a/src/include/access/commit_ts.h +++ b/src/include/access/commit_ts.h @@ -61,6 +61,14 @@ typedef struct xl_commit_ts_set #define SizeOfCommitTsSet (offsetof(xl_commit_ts_set, mainxid) + \ sizeof(TransactionId)) +typedef struct xl_commit_ts_truncate +{ + int pageno; + TransactionId oldestXid; +} xl_commit_ts_truncate; + +#define SizeOfCommitTsTruncate (offsetof(xl_commit_ts_truncate, oldestXid) + \ + sizeof(TransactionId)) extern void commit_ts_redo(XLogReaderState *record); extern void commit_ts_desc(StringInfo buf, XLogReaderState *record); -- cgit v1.2.3