Re: Visibility bug in tuple lock
Jasper Smit <jbsmit@gmail.com>
From: Jasper Smit <jbsmit@gmail.com>
To: Heikki Linnakangas <hlinnaka@iki.fi>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2025-12-17T14:51:17Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix bug in following update chain when locking a heap tuple
- b6201c76eba4 14.21 landed
- 5d5487cd256f 15.16 landed
- 7efef18ffc14 16.12 landed
- bb87d7fef103 17.8 landed
- 3e3a80f62c09 18.2 landed
- 955f5506863d 19 (unreleased) landed
> Thanks! That's not quite correct though. This is very subtle, but the > 'tuple' argument to heap_lock_updated_tuple() points to the buffer > holding the original tuple. So doing > HeapTupleHeaderGetUpdateXid(tuple->t_data) reads the current xmax of the > tuple, which can now be different than what it was earlier, i.e. > different from the xwait that we waited for. It's important that the > 'ctid' and 'priorXmax' that we use to follow the chain are read together. Oops, you are right, I was too quick, it has already been quite some time since i was dealing with this problem initially. I see you moved the check ItemPointerEquals(&tuple->t_self, ctid) out to heap_lock_tuple() but isn't this redundant in the check `if (follow_updates && updated && !ItemPointerEquals(&tuple->t_self, &t_ctid))` if `updated` is already true in this condition? Also in `heap_lock_updated_tuple_rec()` is the check for `TransactionIdIsValid(priorXmax)` now redundant too? / * Locking the initial tuple where those * values came from is the caller's responsibility. */ I think this is still ambiguous, you can still interpret that as the initial tuple needs to be locked before the function is called. Maybe it is better to change it to something like: "This function will not lock the initial tuple." Unrelated question, I was wondering why these functions take a "const ItemPointerData *" as an argument as opposed to just pass the ctid by value? Jasper