| Subcribe via RSS

pg_stat_activity shows future queries!

September 11th, 2012 Posted in Postgres, Uncategorized

This morning I was working on getting some statistics on average transaction open time on a relatively underutilized host when I noticed some oddities. Periodically, I would see that my average duration of open transactions would dip below zero seconds. As I looked into it, I came across the following result from a simple query to pg_stat_activity:

postgres=# SELECT xact_start, NOW() AS now FROM pg_stat_activity WHERE xact_start IS NOT NULL;
-[ RECORD 1 ]----------------------------
xact_start | 2012-09-11 19:33:41.253139+00 <-- Note this happens AFTER NOW() (i.e. in the future)
now        | 2012-09-11 19:33:41.252795+00
...

Naturally, PostgreSQL isn’t predicting future queries, but it is obvious that there are some issues with recorded vs. reported transaction start times. Digging a bit deeper into src/backend/access/transam/xact.c and src/backend/postmaster/pgstat.c, it became clear to me why this behavior manifests:

1743   /*
1744    * set transaction_timestamp() (a/k/a now()).  We want this to be the same
1745    * as the first command's statement_timestamp(), so don't do a fresh
1746    * GetCurrentTimestamp() call (which'd be expensive anyway).  Also, mark
1747    * xactStopTimestamp as unset.
1748    */
1749   xactStartTimestamp = stmtStartTimestamp;
1750   xactStopTimestamp = 0;
1751   pgstat_report_xact_timestamp(xactStartTimestamp);

Of course, this appears simply to be an implementation detail that probably won’t affect most users, but it’s certainly something to be aware of! For me, the solution to this is to simply normalize all negative intervals to zero and use that to calculate average current transaction duration.

Be Sociable, Share!

2 Responses to “pg_stat_activity shows future queries!”

  1. Phil Sorber Says:

    There are several functions that you might want to take a look at.

    clock_timestamp(), statement_timestamp(), and transaction_timestamp(). As you discovered now() is the same as transaction_timestamp(). statement_timestamp() is the same as the beginning of your statement and clock_timestamp() will change throughout your statement.

    More info here: http://www.postgresql.org/docs/9.1/interactive/functions-datetime.html#FUNCTIONS-DATETIME-TABLE


  2. rlowe Says:

    Yeah, it was a bit confusing when it didn’t behave as expected and having to dive into the source.

    Another fun item is that clock_timestamp() can-and-will return different results within the same query (also in the “documented but surprising the first time you see it” category)

    postgres=# SELECT clock_timestamp(), statement_timestamp(), transaction_timestamp(), NOW(), clock_timestamp();
    -[ RECORD 1 ]---------+------------------------------
    clock_timestamp       | 2012-09-12 02:59:11.439232+00
    statement_timestamp   | 2012-09-12 02:59:11.43909+00
    transaction_timestamp | 2012-09-12 02:59:11.43909+00
    now                   | 2012-09-12 02:59:11.43909+00
    clock_timestamp       | 2012-09-12 02:59:11.439234+00
    

Leave a Reply

*