Hi,

While working on another logical replication feature, I noticed a bug: the
apply worker uses a raw xmin that may have been frozen when fetching tuple info
for conflict detection and reporting.

The reason is that, GetTupleTransactionInfo() used slot_getsysattr() with
MinTransactionIdAttributeNumber to fetch the local tuple's xmin.
However, heap_getsysattr() calls HeapTupleHeaderGetRawXmin(), which
returns the raw 32-bit t_xmin from the tuple header even when the tuple
is marked frozen (HEAP_XMIN_FROZEN).

Once a tuple is frozen, its raw t_xmin is retained only for debugging
purposes; its commit timestamp entry may no longer be valid, or the
32-bit XID may have wrapped around and been reassigned in a later epoch.
Using the raw xmin of a frozen tuple could therefore trigger spurious
update_origin_differs or delete_origin_differs conflicts, or report
bogus transaction ID, origin, and commit timestamp details for unique
constraint conflicts.

Attaching a patch fixing this by fetching the tuple via
ExecFetchSlotHeapTuple() and calling HeapTupleHeaderGetXmin(), returning
InvalidTransactionId and skipping the commit timestamp lookup when the tuple's
xmin is not a normal transaction ID. Also update errdetail_apply_conflict() to
omit the transaction ID from unique-conflict detail messages when localxmin is
invalid.

-- 
Best Regards,
Zhijie Hou

Attachment: v1-0001-Avoid-using-raw-xmin-of-frozen-tuples-in-conflict.patch
Description: Binary data

Reply via email to