Skip to content

Commit

Permalink
Don't follow update chains unless caller requests it
Browse files Browse the repository at this point in the history
Some code paths must not follow chains -- they will be followed by the EvalPlanQual
mechanism.  Doing both causes deadlocks.
  • Loading branch information
alvherre committed Apr 2, 2012
1 parent 48cd8cc commit e00e682
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 12 deletions.
21 changes: 13 additions & 8 deletions src/backend/access/heap/heapam.c
Original file line number Diff line number Diff line change
Expand Up @@ -3683,6 +3683,8 @@ get_mxact_status_for_lock(LockTupleMode mode, bool is_update)
* tuple's cmax if lock is successful)
* mode: indicates if shared or exclusive tuple lock is desired
* nowait: if true, ereport rather than blocking if lock not available
* follow_updates: if true, follow the update chain to also lock descendant
* tuples.
*
* Output parameters:
* *tuple: all fields filled in
Expand All @@ -3706,7 +3708,8 @@ get_mxact_status_for_lock(LockTupleMode mode, bool is_update)
HTSU_Result
heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
ItemPointer ctid, TransactionId *update_xmax,
CommandId cid, LockTupleMode mode, bool nowait)
CommandId cid, LockTupleMode mode, bool nowait,
bool follow_updates)
{
HTSU_Result result;
ItemPointer tid = &(tuple->t_self);
Expand Down Expand Up @@ -3845,10 +3848,12 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
if ((mode == LockTupleKeyShare) &&
!(infomask2 & HEAP_UPDATE_KEY_REVOKED))
{
bool not_updated = false;
bool updated;

updated = !HeapTupleHeaderInfomaskIsOnlyLocked(infomask);

/* if there are updates, follow the update chain */
if (!HeapTupleHeaderInfomaskIsOnlyLocked(infomask))
if (follow_updates && updated)
{
HTSU_Result res;

Expand All @@ -3863,8 +3868,6 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
goto failed;
}
}
else
not_updated = true;

LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);

Expand All @@ -3876,7 +3879,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
*/
if (!HeapTupleHeaderIsOnlyLocked(tuple->t_data) &&
((tuple->t_data->t_infomask2 & HEAP_UPDATE_KEY_REVOKED) ||
not_updated))
!updated))
goto l3;
require_sleep = false;

Expand Down Expand Up @@ -4013,7 +4016,8 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
MultiXactIdWait((MultiXactId) xwait, status, &remain, infomask);

/* if there are updates, follow the update chain */
if (!HeapTupleHeaderInfomaskIsOnlyLocked(infomask))
if (follow_updates &&
!HeapTupleHeaderInfomaskIsOnlyLocked(infomask))
{
HTSU_Result res;

Expand Down Expand Up @@ -4066,7 +4070,8 @@ heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
XactLockTableWait(xwait);

/* if there are updates, follow the update chain */
if (!HeapTupleHeaderInfomaskIsOnlyLocked(infomask))
if (follow_updates &&
!HeapTupleHeaderInfomaskIsOnlyLocked(infomask))
{
HTSU_Result res;

Expand Down
2 changes: 1 addition & 1 deletion src/backend/commands/trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -2601,7 +2601,7 @@ ltrmark:;
test = heap_lock_tuple(relation, &tuple, &buffer,
&update_ctid, &update_xmax,
estate->es_output_cid,
LockTupleUpdate, false);
LockTupleUpdate, false, false);
switch (test)
{
case HeapTupleSelfUpdated:
Expand Down
2 changes: 1 addition & 1 deletion src/backend/executor/execMain.c
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
test = heap_lock_tuple(relation, &tuple, &buffer,
&update_ctid, &update_xmax,
estate->es_output_cid,
lockmode, false);
lockmode, false, false);
/* We now have two pins on the buffer, get rid of one */
ReleaseBuffer(buffer);

Expand Down
2 changes: 1 addition & 1 deletion src/backend/executor/nodeLockRows.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ ExecLockRows(LockRowsState *node)
test = heap_lock_tuple(erm->relation, &tuple, &buffer,
&update_ctid, &update_xmax,
estate->es_output_cid,
lockmode, erm->noWait);
lockmode, erm->noWait, true);
ReleaseBuffer(buffer);
switch (test)
{
Expand Down
2 changes: 1 addition & 1 deletion src/include/access/heapam.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ extern HTSU_Result heap_update(Relation relation, ItemPointer otid,
extern HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
Buffer *buffer, ItemPointer ctid,
TransactionId *update_xmax, CommandId cid,
LockTupleMode mode, bool nowait);
LockTupleMode mode, bool nowait, bool follow_update);
extern void heap_inplace_update(Relation relation, HeapTuple tuple);
extern bool heap_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
TransactionId cutoff_multi, Buffer buf);
Expand Down

0 comments on commit e00e682

Please sign in to comment.