diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index fe4ab667ec..4066f6e72b 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -949,6 +949,22 @@ read_info(SeqTable elm, Relation rel, Buffer *buf) Assert(ItemIdIsNormal(lp)); tuple.t_data = (HeapTupleHeader) PageGetItem((Page) 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 */