Alvaro Herrera wrote:
> I'm thinking about the comparison of full infomask as you propose
> instead of just the bits that we actually care about. I think the only
> thing that could cause a spurious failure (causing an extra execution of
> the HeapTupleSatisfiesUpdate call and the stuff below) is somebody
> setting HEAP_XMIN_COMMITTED concurrently; but that seems infrequent
> enough that it should pretty harmless. However, should we worry about
> possible future infomask bit changes that could negatively affect this
> behavior?
Here's a complete patch illustrating what I mean. This is slightly more
expensive than straight infomask comparison in terms of machine
instructions, but that seems okay to me.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
*** a/src/backend/access/heap/heapam.c
--- b/src/backend/access/heap/heapam.c
***************
*** 2586,2591 **** compute_infobits(uint16 infomask, uint16 infomask2)
--- 2586,2612 ----
}
/*
+ * Given two versions of the same t_infomask for a tuple, compare them and
+ * return whether the relevant status for a tuple Xmax has changed. This is
+ * used after a buffer lock has been released and reacquired: we want to ensure
+ * that the tuple state continues to be the same it was when we previously
+ * examined it.
+ *
+ * Note the Xmax field itself must be compared separately.
+ */
+ static inline bool
+ xmax_infomsk_changed(uint16 infomask1, uint16 infomask2)
+ {
+ const uint16 interesting =
+ HEAP_XMAX_IS_MULTI | HEAP_XMAX_LOCK_ONLY | HEAP_LOCK_MASK;
+
+ if ((infomask1 & interesting) != (infomask2 & interesting))
+ return true;
+
+ return false;
+ }
+
+ /*
* heap_delete - delete a tuple
*
* NB: do not call this directly unless you are prepared to deal with
***************
*** 2722,2728 **** l1:
* update this tuple before we get to this point. Check for xmax
* change, and start over if so.
*/
! if (!(tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
xwait))
goto l1;
--- 2743,2749 ----
* update this tuple before we get to this point. Check for xmax
* change, and start over if so.
*/
! if (xmax_infomsk_changed(tp.t_data->t_infomask, infomask) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
xwait))
goto l1;
***************
*** 2748,2754 **** l1:
* other xact could update this tuple before we get to this point.
* Check for xmax change, and start over if so.
*/
! if ((tp.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
xwait))
goto l1;
--- 2769,2775 ----
* other xact could update this tuple before we get to this point.
* Check for xmax change, and start over if so.
*/
! if (xmax_infomsk_changed(tp.t_data->t_infomask, infomask) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tp.t_data),
xwait))
goto l1;
***************
*** 3275,3281 **** l2:
* update this tuple before we get to this point. Check for xmax
* change, and start over if so.
*/
! if (!(oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
goto l2;
--- 3296,3302 ----
* update this tuple before we get to this point. Check for xmax
* change, and start over if so.
*/
! if (xmax_infomsk_changed(oldtup.t_data->t_infomask, infomask) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
goto l2;
***************
*** 3324,3335 **** l2:
if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) && key_intact)
{
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-
/*
* recheck the locker; if someone else changed the tuple while
* we weren't looking, start over.
*/
! if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
--- 3345,3355 ----
if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) && key_intact)
{
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
* recheck the locker; if someone else changed the tuple while
* we weren't looking, start over.
*/
! if (xmax_infomsk_changed(oldtup.t_data->t_infomask, infomask) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
***************
*** 3350,3356 **** l2:
* some other xact could update this tuple before we get to
* this point. Check for xmax change, and start over if so.
*/
! if ((oldtup.t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
--- 3370,3376 ----
* some other xact could update this tuple before we get to
* this point. Check for xmax change, and start over if so.
*/
! if (xmax_infomsk_changed(oldtup.t_data->t_infomask, infomask) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(oldtup.t_data),
xwait))
***************
*** 4354,4360 **** l3:
* over.
*/
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
! if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
{
--- 4374,4380 ----
* over.
*/
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
! if (xmax_infomsk_changed(tuple->t_data->t_infomask, infomask) ||
!TransactionIdEquals(HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
{
***************
*** 4373,4379 **** l3:
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/* if the xmax changed in the meantime, start over */
! if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
--- 4393,4399 ----
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/* if the xmax changed in the meantime, start over */
! if (xmax_infomsk_changed(tuple->t_data->t_infomask, infomask) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
***************
*** 4441,4447 **** l3:
* could update this tuple before we get to this point. Check
* for xmax change, and start over if so.
*/
! if (!(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
--- 4461,4467 ----
* could update this tuple before we get to this point. Check
* for xmax change, and start over if so.
*/
! if (xmax_infomsk_changed(tuple->t_data->t_infomask, infomask) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
***************
*** 4497,4503 **** l3:
* some other xact could update this tuple before we get to
* this point. Check for xmax change, and start over if so.
*/
! if ((tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
--- 4517,4523 ----
* some other xact could update this tuple before we get to
* this point. Check for xmax change, and start over if so.
*/
! if (xmax_infomsk_changed(tuple->t_data->t_infomask, infomask) ||
!TransactionIdEquals(
HeapTupleHeaderGetRawXmax(tuple->t_data),
xwait))
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers