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:
parent
57b100fe0f
commit
86073a2b7a
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user