TuplesAs seen in 5.7 PostgreSQL when updating the rows, generates new row versions stamping the old as dead.
Each tuple comes with a fixed header of system columns usually 23 bytes as shown in the figure 6.3.
The field t_cid is a ``virtual'' field used either for cmin and cmax. This is possible because the command id have meaning only inside a transaction.
The field t_xvac is used by VACUUM when moving the rows, according with the source code's comments in src/include/access/htup_details.h this is used only by old style VACUUM FULL.
The t_cid is the tuple's location id, a couple of integers pointing the page number and the tuple's index. When a new tuple is created t_cid is set to the actual row's value; When the tuple is updated the this value changes to the location of the newer tuple's version.
A tuple is then recognised as last versino when xmax is invalid or t_cid points to itself. If xmax is also valid then the tuple is the last locked or deleted version of the tuple's version chain.
The two infomask fields are used to store various flags like the presence of the tuple OID or if the tuple has NULL values.
The last field t_off is used to mark the offset to the composite data, the actual tuple's data. This field's value is usually zero if the table doesn't have NULLable fields or is created WITH OIDS. The OID and the a bitmap are then placed just after the header's. The bitmap begins just after the fixed header and occupies enough bytes to have one bit per data column. The OID comes after and is 4 bytes long.