mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Revert "For inplace update, send nontransactional invalidations."
This reverts commit 95c5acb3fc
(v17) and
counterparts in each other non-master branch. If released, that commit
would have caused a worst-in-years minor release regression, via
undetected LWLock self-deadlock. This commit and its self-deadlock fix
warrant more bake time in the master branch.
Reported by Alexander Lakhin.
Discussion: https://postgr.es/m/10ec0bc3-5933-1189-6bb8-5dec4114558e@gmail.com
This commit is contained in:
@ -6306,24 +6306,6 @@ heap_inplace_update_and_unlock(Relation relation,
|
||||
if (oldlen != newlen || htup->t_hoff != tuple->t_data->t_hoff)
|
||||
elog(ERROR, "wrong tuple length");
|
||||
|
||||
/*
|
||||
* Construct shared cache inval if necessary. Note that because we only
|
||||
* pass the new version of the tuple, this mustn't be used for any
|
||||
* operations that could change catcache lookup keys. But we aren't
|
||||
* bothering with index updates either, so that's true a fortiori.
|
||||
*/
|
||||
CacheInvalidateHeapTupleInplace(relation, tuple, NULL);
|
||||
|
||||
/*
|
||||
* Unlink relcache init files as needed. If unlinking, acquire
|
||||
* RelCacheInitLock until after associated invalidations. By doing this
|
||||
* in advance, if we checkpoint and then crash between inplace
|
||||
* XLogInsert() and inval, we don't rely on StartupXLOG() ->
|
||||
* RelationCacheInitFileRemove(). That uses elevel==LOG, so replay would
|
||||
* neglect to PANIC on EIO.
|
||||
*/
|
||||
PreInplace_Inval();
|
||||
|
||||
/* NO EREPORT(ERROR) from here till changes are logged */
|
||||
START_CRIT_SECTION();
|
||||
|
||||
@ -6367,28 +6349,17 @@ heap_inplace_update_and_unlock(Relation relation,
|
||||
PageSetLSN(BufferGetPage(buffer), recptr);
|
||||
}
|
||||
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
|
||||
/*
|
||||
* Send invalidations to shared queue. SearchSysCacheLocked1() assumes we
|
||||
* do this before UnlockTuple().
|
||||
*
|
||||
* If we're mutating a tuple visible only to this transaction, there's an
|
||||
* equivalent transactional inval from the action that created the tuple,
|
||||
* and this inval is superfluous.
|
||||
*/
|
||||
AtInplace_Inval();
|
||||
|
||||
END_CRIT_SECTION();
|
||||
UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock);
|
||||
|
||||
AcceptInvalidationMessages(); /* local processing of just-sent inval */
|
||||
heap_inplace_unlock(relation, oldtup, buffer);
|
||||
|
||||
/*
|
||||
* Queue a transactional inval. The immediate invalidation we just sent
|
||||
* is the only one known to be necessary. To reduce risk from the
|
||||
* transition to immediate invalidation, continue sending a transactional
|
||||
* invalidation like we've long done. Third-party code might rely on it.
|
||||
* Send out shared cache inval if necessary. Note that because we only
|
||||
* pass the new version of the tuple, this mustn't be used for any
|
||||
* operations that could change catcache lookup keys. But we aren't
|
||||
* bothering with index updates either, so that's true a fortiori.
|
||||
*
|
||||
* XXX ROLLBACK discards the invalidation. See test inplace-inval.spec.
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode())
|
||||
CacheInvalidateHeapTuple(relation, tuple, NULL);
|
||||
|
Reference in New Issue
Block a user