summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-06-02 15:31:14 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-06-02 15:31:14 -0400
commit918eb0f34f2af3e0d2823a164d22b6906d46dfcd (patch)
tree09fd57a20b0fa0de6d546263bf0a2dae04084ecb
parent23138a5203fe14d6adf5019482f341ebfe2136ad (diff)
downloadpostgresql-918eb0f34f2af3e0d2823a164d22b6906d46dfcd.tar.gz
Clean up after erroneous SELECT FOR UPDATE/SHARE on a sequence.
My previous commit disallowed this operation, but did nothing about cleaning up the damage if one had already been done. With the operation disallowed, it's okay to just forcibly clear xmax in a sequence's tuple, since any value seen there could not represent a live transaction's lock. So, any sequence-specific operation will repair the problem automatically, whether or not the user has already seen "could not access status of transaction" failures.
-rw-r--r--src/backend/commands/sequence.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index e6c75ab014..27c2f174f2 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -974,6 +974,22 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
Assert(ItemIdIsNormal(lp));
tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
+ /*
+ * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE
+ * on a sequence, which would leave a non-frozen XID in the sequence
+ * tuple's xmax, which eventually leads to clog access failures or worse.
+ * If we see this has happened, clean up after it. We treat this like a
+ * hint bit update, ie, don't bother to WAL-log it, since we can certainly
+ * do this again if the update gets lost.
+ */
+ if (HeapTupleHeaderGetXmax(tuple.t_data) != InvalidTransactionId)
+ {
+ HeapTupleHeaderSetXmax(tuple.t_data, InvalidTransactionId);
+ tuple.t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
+ tuple.t_data->t_infomask |= HEAP_XMAX_INVALID;
+ SetBufferCommitInfoNeedsSave(*buf);
+ }
+
seq = (Form_pg_sequence) GETSTRUCT(&tuple);
/* this is a handy place to update our copy of the increment */