1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-08 22:02:03 +03:00

Correctly detect SSI conflicts of prepared transactions after crash.

A prepared transaction can get new conflicts in and out after preparing, so
we cannot rely on the in- and out-flags stored in the statefile at prepare-
time. As a quick fix, make the conservative assumption that after a restart,
all prepared transactions are considered to have both in- and out-conflicts.
That can lead to unnecessary rollbacks after a crash, but that shouldn't be
a big problem in practice; you don't want prepared transactions to hang
around for a long time anyway.

Dan Ports
This commit is contained in:
Heikki Linnakangas 2012-02-29 15:22:49 +02:00
parent 57b100fe0f
commit 86073a2b7a

View File

@ -4659,14 +4659,11 @@ AtPrepare_PredicateLocks(void)
xactRecord->flags = MySerializableXact->flags; xactRecord->flags = MySerializableXact->flags;
/* /*
* Tweak the flags. Since we're not going to output the inConflicts and * Note that we don't include the list of conflicts in our out in
* outConflicts lists, if they're non-empty we'll represent that by * the statefile, because new conflicts can be added even after the
* setting the appropriate summary conflict flags. * transaction prepares. We'll just make a conservative assumption
* during recovery instead.
*/ */
if (!SHMQueueEmpty(&MySerializableXact->inConflicts))
xactRecord->flags |= SXACT_FLAG_SUMMARY_CONFLICT_IN;
if (!SHMQueueEmpty(&MySerializableXact->outConflicts))
xactRecord->flags |= SXACT_FLAG_SUMMARY_CONFLICT_OUT;
RegisterTwoPhaseRecord(TWOPHASE_RM_PREDICATELOCK_ID, 0, RegisterTwoPhaseRecord(TWOPHASE_RM_PREDICATELOCK_ID, 0,
&record, sizeof(record)); &record, sizeof(record));
@ -4801,15 +4798,6 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info,
sxact->SeqNo.lastCommitBeforeSnapshot = RecoverySerCommitSeqNo; sxact->SeqNo.lastCommitBeforeSnapshot = RecoverySerCommitSeqNo;
/*
* We don't need the details of a prepared transaction's conflicts,
* just whether it had conflicts in or out (which we get from the
* flags)
*/
SHMQueueInit(&(sxact->outConflicts));
SHMQueueInit(&(sxact->inConflicts));
/* /*
* Don't need to track this; no transactions running at the time the * Don't need to track this; no transactions running at the time the
* recovered xact started are still active, except possibly other * recovered xact started are still active, except possibly other
@ -4831,6 +4819,17 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info,
(MaxBackends + max_prepared_xacts)); (MaxBackends + max_prepared_xacts));
} }
/*
* We don't know whether the transaction had any conflicts or
* not, so we'll conservatively assume that it had both a
* conflict in and a conflict out, and represent that with the
* summary conflict flags.
*/
SHMQueueInit(&(sxact->outConflicts));
SHMQueueInit(&(sxact->inConflicts));
sxact->flags |= SXACT_FLAG_SUMMARY_CONFLICT_IN;
sxact->flags |= SXACT_FLAG_SUMMARY_CONFLICT_OUT;
/* Register the transaction's xid */ /* Register the transaction's xid */
sxidtag.xid = xid; sxidtag.xid = xid;
sxid = (SERIALIZABLEXID *) hash_search(SerializableXidHash, sxid = (SERIALIZABLEXID *) hash_search(SerializableXidHash,