I\'m working on a design for a concurrency-safe incremental aggregate rollup system,and track_commit_timestamp (pg_xact_commit_timestamp) sounds perfect. But I\'ve found ver
Lots of questions.
For a reference, the source code is in src/backend/access/transam/commit_ts.c
.
I am not sure if it can be guaranteed that a later commit log sequence number implies a later timestamp. I would certainly not rely totally on it if the system clock can jump backwards due to time adjustments.
The timestamp is not stored in the row at all, but in the pg_commit_ts
subdirectory of the data directory. Each record takes 10 bytes:
/*
* We need 8+2 bytes per xact. Note that enlarging this struct might mean
* the largest possible file name is more than 5 chars long; see
* SlruScanDirectory.
*/
typedef struct CommitTimestampEntry
{
TimestampTz time;
RepOriginId nodeid;
} CommitTimestampEntry;
There is also information about commit timestamps in the transaction log so it can be recovered.
No index is needed, because the location of the timestamp is determined by the transaction number (each transaction has a fixed location for the commit timestamp). See TransactionIdToCTsPage
.
Timestamps are kept as long as transaction numbers, if I understand the code correctly.
I can't tell what the overhead is, but it probably isn't huge.
Why should VACUUM
or VACUUM (FULL)
change the commit timestamp? That would be a bug.
Now that I understand what you want to achieve with commit timestamps, a word to that (I wish people would state the real question right away):
Commit timestamps are not the right tool for you. You could not index the expression, because pg_xact_commit_timestamp
is not immutable.
Choose the simple and obvious solution and add an extra timestamp with time zone
column with a BEFORE
trigger that sets it to current_timestamp
on INSERT
and UPDATE
. That can be indexed.
A famous man has said that premature optimization is the root of all evil.