diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2017-01-19 18:23:09 -0300 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2017-01-19 18:24:17 -0300 |
commit | 8eace46d34ab6ac0d887aa4d3504bc4222c2e448 (patch) | |
tree | 1e6d8a76c81c56b452eff3885381f7d998aee7f7 /src/backend/commands | |
parent | 8b0fec93ecc788c8d8b329d41ab795712d8dcc5a (diff) | |
download | postgresql-8eace46d34ab6ac0d887aa4d3504bc4222c2e448.tar.gz postgresql-8eace46d34ab6ac0d887aa4d3504bc4222c2e448.zip |
Fix race condition in reading commit timestamps
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
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/vacuum.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 0f72c1c36ad..812fb4a48fe 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1153,6 +1153,15 @@ vac_truncate_clog(TransactionId frozenXID, return; /* + * Advance the oldest value for commit timestamps before truncating, so + * that if a user requests a timestamp for a transaction we're truncating + * away right after this point, they get NULL instead of an ugly "file not + * found" error from slru.c. This doesn't matter for xact/multixact + * because they are not subject to arbitrary lookups from users. + */ + AdvanceOldestCommitTsXid(frozenXID); + + /* * Truncate CLOG, multixact and CommitTs to the oldest computed value. */ TruncateCLOG(frozenXID); @@ -1167,7 +1176,6 @@ vac_truncate_clog(TransactionId frozenXID, */ SetTransactionIdLimit(frozenXID, oldestxid_datoid); SetMultiXactIdLimit(minMulti, minmulti_datoid); - AdvanceOldestCommitTsXid(frozenXID); } |