From 217dc525c08c2835f321ca45309601e8b1f57fec Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 8 Jan 2010 02:44:00 +0000
Subject: [PATCH] Fix oversight in EvalPlanQualFetch: after failing to lock a
 tuple because someone else has just updated it, we have to set priorXmax to
 that tuple's xmax (ie, the XID of the other xact that updated it) before
 looping back to examine the next tuple.  Obviously, the next tuple in the
 update chain should have that XID as its xmin, not the same xmin as the
 preceding tuple that we had been trying to lock.  The mismatch would cause
 the EvalPlanQual logic to decide that the tuple chain ended in a deletion,
 when actually there was a live tuple that should have been found.

I inserted this error when recently adding logic to EvalPlanQual to make it
lock tuples before returning them (as opposed to the old method in which the
lock would occur much later, causing a great deal of work to be wasted if we
only then discover someone else updated it).  Sigh.  Per today's report from
Takahiro Itagaki of inconsistent results during pgbench runs.
---
 src/backend/executor/execMain.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 203ed8d928a..8d7adfffbb6 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.340 2010/01/06 03:04:01 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.341 2010/01/08 02:44:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1546,6 +1546,8 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
 					{
 						/* it was updated, so look at the updated version */
 						tuple.t_self = update_ctid;
+						/* updated row should have xmin matching this xmax */
+						priorXmax = update_xmax;
 						continue;
 					}
 					/* tuple was deleted, so give up */
-- 
GitLab