| From: | Takeshi Ideriha <iderihatakeshi(at)gmail(dot)com> |
|---|---|
| To: | Michael Paquier <michael(at)paquier(dot)xyz>, Zhijie Hou <houzhijie22(at)gmail(dot)com> |
| Cc: | shihao zhong <zhong950419(at)gmail(dot)com>, Ayush Tiwari <ayushtiwari(dot)slg01(at)gmail(dot)com>, alpkeles99(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19760: CLUSTER loses a row the transaction inserted and then updated in a rolled-back subtransaction |
| Date: | 2026-10-22 07:46:44 |
| Message-ID: | b05bbcc6-2e3e-4bbe-a661-4dce890e5c6e@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi
On 2026/10/22 11:22, Michael Paquier wrote:
> On Wed, Oct 21, 2026 at 06:01:28PM +0800, Zhijie Hou wrote:
>> + if (!(tuple->t_infomask & HEAP_XMAX_INVALID) &&
>> + !HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) &&
>> + !HeapTupleHeaderIsOnlyLocked(tuple))
>> + {
>> + TransactionId xmax = HeapTupleHeaderGetUpdateXid(tuple);
>> +
>> + if (!TransactionIdIsInProgress(xmax) &&
>> + !TransactionIdDidCommit(xmax))
>> + SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
>> + InvalidTransactionId);
>>
>> If a tuple's Xmax is a MultiXact and the updating subtransaction is still in
>> progress when HeapTupleHeaderIsOnlyLocked() is called, it returns false.
>> However, if that updating subtransaction aborts before the second
>> TransactionIdIsInProgress() check, the second check returns false and sets
>> HEAP_XMAX_INVALID on the tuple even though the MultiXact still has active
>> members, which I think violates the MultiXact hint-bit standard.
>
> Perhaps also check for HEAP_XMAX_IS_MULTI to skip the multixacts and
> make sure that active members are not lost, then? I am not completely
> sure if this would be always right, though, these code paths are the
> hard-level definition of tricky.
>
I'm +1 for fixing the subtransaction issue first but let me add a
comment regarding this multixact race issue.
It should be OK not to set the hint bit for a tuple whose xmax is
MultiXact containing a key locker and an aborted updating
subtransaction. This is because rewrite_heap_tuple filters out this
tuple by HeapTupleHeaderIsOnlyLocked and doesn't put it into unresolved
table. I'm not sure if there is another issue we need to consider in
addition to the performance issue.
Regards,
Takeshi Ideriha
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Michael Paquier | 2026-10-22 08:28:23 | Re: pg_stat_statements replaces SQL/JSON ON EMPTY / ON ERROR keywords with parameters |
| Previous Message | Fujii Masao | 2026-10-22 07:06:51 | Re: START_REPLICATION silently truncates an overlong LSN component |