On Tue, Feb 14, 2012 at 09:27:58AM -0600, Kevin Grittner wrote: > Heikki Linnakangas <heikki.linnakan...@enterprisedb.com> wrote: > > On 14.02.2012 04:57, Dan Ports wrote: > >> The easiest answer would be to just treat every prepared > >> transaction found during recovery as though it had a conflict in > >> and out. This is roughly a one-line change, and it's certainly > >> safe. > > Dan, could you post such a patch, please?
Sure. See attached. > Should we add anything to the docs to warn people that if they crash > with serializable prepared transactions pending, they will see this > behavior until the prepared transactions are either committed or > rolled back, either by the transaction manager or through manual > intervention? Hmm, it occurs to me if we have to abort a transaction due to serialization failure involving a prepared transaction, we might want to include the prepared transaction's gid in the errdetail. This semes like it'd be especially useful for prepared transactions. We can generally pick the transaction to abort to ensure the safe retry property -- if that transaction is immediately retried, it won't fail with the same conflict -- but we can't always guarantee that when prepared transactions are involved. And prepared transactions already have a convenient, user-visible ID we can report. Dan -- Dan R. K. Ports MIT CSAIL http://drkp.net/
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index b75b73a..b102e19 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -4733,14 +4733,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)); @@ -4875,15 +4872,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 @@ -4905,6 +4893,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,
-- Sent via pgsql-hackers mailing list (email@example.com) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers