On Tue, Sep 9, 2025 at 10:18 PM, Chao Li <[email protected]> wrote: > No, that’s not true. If you extend David’s procedure and use 3 sessions to > reproduce the problem, s1 update (0,1), s2 update (0,2) and s3 update (0,1) > or (0,2), and trace the backend process of s3, you will see every time when > TidRecheck() is called, “node” is brand new, so it has to call > TidListEval(node) every time.
After more investigation I agree you are correct here; in a single query, ReScan is called once for each subsequent tuple being rechecked. (ExecUpdate calls EvalPlanQualBegin which always sets rcplanstate->chgParam.) On Wed, Sep 10, 2025 at 10:30 PM, Chao Li <[email protected]> wrote: > But, why can't we make TidRecheck() to simplify return FALSE? > > Looks like the only case where TidRecheck() is called is a concurrent > transaction upadated the row, and in that case, ctid have must be changed. Although returning FALSE is clever, it is only correct if several other unstated preconditions for the function hold, which I am loath to rely on. And indeed, like I mentioned in my previous message, my isolation test `permutation tid1 tidsucceed2 c1 c2 read` from eval-plan-qual.spec in my patch will fail if Recheck were to return false in this case. Though somewhat contrived, you can imagine this happening with multiple sessions driven by the same application: setup: two rows exist with ctid=(0,1) and (0,2) S1: BEGIN; S2: BEGIN; S1: UPDATE WHERE ctid=(0,1) RETURNING ctid; -- returns (0,3), which the application uses in the next query from another session: S2: UPDATE WHERE ctid=(0,1) OR ctid=(0,3); -- statement snapshot sees (0,1); recheck will see (0,3) and should pass S1: COMMIT; S2: COMMIT; I would not defend this as good code from an application developer but the behavior is observable. So I understand it would be best to match the enable_tidscan = off behavior, which my existing strategy more verifiably does. Of course if the team disagrees with me then I will defer to everyone's better judgement. I hope it is rare that many tuples need to be rechecked in a single query but if this is common, then I would suggest it would be better to rework the generic EPQ machinery so that EPQ nodes do not need to be not reset for every row, rather than depending on subtle implicit guarantees in the TidRecheck code. Sophie
