[PostgreSQL] PostgreSQL での現在時刻取得

PostgreSQL で現在時刻を取得しようとして now() 関数を使うと、えらく古い時刻を返されることがある。

実は PostgreSQL の now() 関数は、その関数が評価されたタイミングの時刻ではなく、トランザクションを開始した時刻を返す。それはそれで使い道があるのかもしれないけど、知らないとはまる。

まあトランザクションの開始時刻でもほぼ現在時刻とかわらんでしょと思うかもしれないけど、コネクションプーリングの実装によっては、トランザクションを開始した状態でコネクションをプールさせておき、そのコネクションをそのまま提供するものがある(commons-dbcp がそうだった)。そうした場合、now() で返される時刻は最後にそのプールされたコネクションが返却された時刻になるので、相当古い時刻を返すことがある。

そうした問題があるためか、PostgreSQL は 8.2 でいくつかの種類の現在時刻を取得する関数が追加された。

transaction_timestamp()
now() と同じで、現在のトランザクションの開始時刻を返す。
statement_timestamp()
現在の問い合わせがサーバに届いた時刻を返す。したがって同じSQL文の中で複数呼び出しても同じ時刻が返ってくる。
clock_timestamp()
実際の現在時刻を返す。同じSQL文の中で複数呼び出しても異なる時間が返ってくる可能性がある。

より厳密な現在時刻を取得したいときなどは、これらの関数を使うことになる。