Alvaro Herrera <alvhe...@2ndquadrant.com> wrote:
> Andres Freund wrote:

>> That's because HeapTupleHeaderGetUpdateXid() ignores aborted
>> updaters and returns InvalidTransactionId in that case, but
>> HeapTupleSatisfiesVacuum() returns
>> HEAPTUPLE_DELETE_IN_PROGRESS...

> I checked for other cases where the update Xid is checked after
> HeapTupleSatisfiesVacuum returns HEAPTUPLE_DELETE_IN_PROGRESS. 
> As far as I can tell, the only one that would be affected is the
> one in predicate.c.  It is far from clear to me what is the right
> thing to do in these cases; the simplest idea is to return
> without reporting a failure if the updater aborted, just as
> above; but I wonder if this needs to be conditional on "visible".
> I added a pg_usleep() before acquiring the update Xid in the
> relevant case, but the isolation test cases didn't hit the
> problem (I presume there is no update/delete in these test cases,
> but I didn't check).  I defer to Kevin on this issue.

Right now if HeapTupleSatisfiesVacuum() returns
HEAPTUPLE_DELETE_IN_PROGRESS we call
HeapTupleHeaderGetUpdateXid(tuple->t_data) and Assert() that the
result is valid.  It sounds like we should do something like the
attached, maybe?

--
Kevin Grittner
EDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index a8a0e98..1f2bf91 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -3907,6 +3907,8 @@ CheckForSerializableConflictOut(bool visible, Relation relation,
 			break;
 		case HEAPTUPLE_DELETE_IN_PROGRESS:
 			xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
+			if (!TransactionIdIsValid(xid))
+				return;
 			break;
 		case HEAPTUPLE_INSERT_IN_PROGRESS:
 			xid = HeapTupleHeaderGetXmin(tuple->t_data);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to