I took another stab at this from a different angle, and tried to use
this to simplify logical decoding. The theory was that if we included
the command ID in the WAL records, we wouldn't need the separate
HEAP2_NEW_CID record anymore, and could remove much of the code in
reorderbuffer.c that's concerned with tracking ctid->(cmin,cmax)
mapping. Unfortunately, it didn't work out.
Here's one problem:
Insert with cmin 1
Commit
Delete the same tuple with cmax 2.
Abort
Even if we store the cmin in the INSERT record, and set it on the tuple
on replay, the DELETE overwrites it. That's OK for the original
transactions, because they only look at the cmin/cmax of their own
transaction, but it's a problem for logical decoding. If we see the
inserted tuple during logical decoding, we need the cmin of the tuple.
We could still just replace the HEAP2_NEW_CID records with the CIDs in
the heap INSERT/UPDATE/DELETE records, and use that information to
maintain the ctid->(cmin,cmax) mapping in reorderbuffer.c like we do
today. But that doesn't really simplify reorderbuffer.c much. Attached
is a patch for that, for the archives sake.
Another problem with that is that logical decoding needs slightly
different information than what we store on the tuples on disk. My
original motivation for this was for Neon, which needs the WAL replay to
restore the same CID as what's stored on disk, whether it's cmin, cmax
or combocid. But for logical decoding, we need the cmin or cmax, *not*
the combocid. To cater for both uses, we'd need to include both the
original cmin/cmax and the possible combocid, which again makes it more
complicated.
So unfortunately I don't see much opportunity to simplify logical
decoding with this. However, please take a look at the first two patches
attached. They're tiny cleanups that make sense on their own.
- Heikki