Обсуждение: Relocation of tuple between release and re-acquire of tuple lock

Поиск
Список
Период
Сортировка

Relocation of tuple between release and re-acquire of tuple lock

От
Alexander Korotkov
Дата:
Hackers,

I'm now exploring code working with heap tuples.  The following code in heap_update() catch my eyes.

if (DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
*lockmode))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
/* acquire tuple lock, if necessary */
heap_acquire_tuplock(relation, &(oldtup.t_self), *lockmode,
LockWaitBlock, &have_tuple_lock);
/* wait for multixact */
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
relation, &oldtup.t_self, XLTW_Update,
&remain);
checked_lockers = true;
locker_remains = remain != 0;
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
* If xwait had just locked the tuple then some other xact
* could update this tuple before we get to this point.  Check
* for xmax change, and start over if so.
*/
if (xmax_infomask_changed(oldtup.t_data->t_infomask,
 infomask) ||
!TransactionIdEquals(HeapTupleGetRawXmax(&oldtup),
xwait))
goto l2;
}

Is it safe to rely on same oldtup.t_data pointer after release and re-acquire of buffer content lock?  Could the heap tuple be relocated between lock release and re-acquire?  I know that we still hold a buffer pin and vacuum would wait for pin release.  But other heap operations could still call heap_page_prune() which correspondingly can relocate tuple.  Probably, I'm missing something...

------
Alexander Korotkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Re: Relocation of tuple between release and re-acquire of tuple lock

От
Alexander Korotkov
Дата:
On Fri, Aug 12, 2016 at 3:15 PM, Alexander Korotkov <a.korotkov@postgrespro.ru> wrote:
I'm now exploring code working with heap tuples.  The following code in heap_update() catch my eyes.

if (DoesMultiXactIdConflict((MultiXactId) xwait, infomask,
*lockmode))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
/* acquire tuple lock, if necessary */
heap_acquire_tuplock(relation, &(oldtup.t_self), *lockmode,
LockWaitBlock, &have_tuple_lock);
/* wait for multixact */
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
relation, &oldtup.t_self, XLTW_Update,
&remain);
checked_lockers = true;
locker_remains = remain != 0;
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
/*
* If xwait had just locked the tuple then some other xact
* could update this tuple before we get to this point.  Check
* for xmax change, and start over if so.
*/
if (xmax_infomask_changed(oldtup.t_data->t_infomask,
 infomask) ||
!TransactionIdEquals(HeapTupleGetRawXmax(&oldtup),
xwait))
goto l2;
}

Is it safe to rely on same oldtup.t_data pointer after release and re-acquire of buffer content lock?  Could the heap tuple be relocated between lock release and re-acquire?  I know that we still hold a buffer pin and vacuum would wait for pin release.  But other heap operations could still call heap_page_prune() which correspondingly can relocate tuple.  Probably, I'm missing something...

Please, forget it. heap_page_prune_opt() do:
 
/* OK, try to get exclusive buffer lock */
if (!ConditionalLockBufferForCleanup(buffer))
return;

Nobody repairs buffer fragmentation while there is a pin. Everything is right.

------
Alexander Korotkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company