diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-02-29 15:22:49 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-02-29 15:42:36 +0200 |
commit | d6a7271958e61fe8029087a34483437292f41f6f (patch) | |
tree | 9702977c5a58323701949336036ebeebbb5188ad /src | |
parent | 8cae5810ebaaabb54171d9953bdd9cc802f0d135 (diff) | |
download | postgresql-d6a7271958e61fe8029087a34483437292f41f6f.tar.gz postgresql-d6a7271958e61fe8029087a34483437292f41f6f.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/storage/lmgr/predicate.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 9e927f85644..08fb69c32e5 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -4730,14 +4730,11 @@ AtPrepare_PredicateLocks(void) xactRecord->flags = MySerializableXact->flags; /* - * Tweak the flags. Since we're not going to output the inConflicts and - * outConflicts lists, if they're non-empty we'll represent that by - * setting the appropriate summary conflict flags. + * Note that we don't include the list of conflicts in our out in + * the statefile, because new conflicts can be added even after the + * 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, &record, sizeof(record)); @@ -4872,15 +4869,6 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info, 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 * recovered xact started are still active, except possibly other @@ -4902,6 +4890,17 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info, (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 */ sxidtag.xid = xid; sxid = (SERIALIZABLEXID *) hash_search(SerializableXidHash, |