aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-02-29 15:22:49 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-02-29 15:43:43 +0200
commit86073a2b7acc58fce8701a9207a46adb41fbd8cc (patch)
tree1b211ccf322759b1ac88c4acafcd957dddc749b1
parent57b100fe0fb1d0d5803789d3113b89fa18a34fad (diff)
downloadpostgresql-86073a2b7acc58fce8701a9207a46adb41fbd8cc.tar.gz
postgresql-86073a2b7acc58fce8701a9207a46adb41fbd8cc.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
-rw-r--r--src/backend/storage/lmgr/predicate.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 27124672da9..532dedf959b 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -4659,14 +4659,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));
@@ -4801,15 +4798,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
@@ -4831,6 +4819,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,