Postgresql システム時刻取得関数について発見
バッチ処理にpl/pgsqlも使ってたりするんですが、
先週たまたまアボートしてログ見てる時に気付いたことが。
あれ、開始と終了の時刻が一緒。
ログ出力で、ストアドの開始と終了に実行日付出してるんですが、
どのストアドみても開始と終了の時刻が一緒になってるんです。
なんで?バグ?
と思って、ドキュメント見直したら仕様でした!
時刻取得にnow()を使ってたんですが、トランザクション内で常に同じ値を返すらしい。
now()はCURRENT_TIMESTAMPと同じもので、伝統的なPostgreSQL関数です。 transaction_timestamp()はCURRENT_TIMESTAMP同様のものですが、明確に何が返されるかを示す名前になっています。 statement_timestamp()は現在の文の実行開始時刻を返すものです(より具体的にいうと、直前のコマンドメッセージをクライアントから受け取った時刻です)。 statement_timestamp()およびtransaction_timestamp()はトランザクションの最初のコマンドでは同じ値を返しますが、その後に引き続くコマンドでは異なる可能性があります。 clock_timestamp()は実際の現在時刻を返しますので、その値は単一のSQLコマンドであっても異なります。
PostgreSQL日本語ドキュメント 9.9. 日付/時刻関数と演算子
なるほどー。トランザクション内で使う場合は
用途で使い分ける必要があるわけですね。
試してみた。
トランザクションなし
postgres=# select now(); now ------------------------------- 2009-02-21 23:34:48.343367+09 (1 row) postgres=# select now(); now ------------------------------ 2009-02-21 23:34:50.44536+09 (1 row)
普通に現在時刻を返す。
トランザクション設定 -> now(), current_timestamp, transaction_timestamp()
postgres=# begin; BEGIN postgres=# select now(); now ------------------------------- 2009-02-21 23:35:00.143057+09 (1 row) postgres=# select now(); now ------------------------------- 2009-02-21 23:35:00.143057+09 (1 row) postgres=# select current_timestamp; now ------------------------------- 2009-02-21 23:35:00.143057+09 (1 row) postgres=# select transaction_timestamp(); transaction_timestamp ------------------------------- 2009-02-21 23:35:00.143057+09 (1 row)
何度実行しても結果は一緒。
トランザクション設定 -> statement_timestamp(), clock_timestamp();
postgres=# select now(); now ------------------------------- 2009-02-21 23:35:00.143057+09 (1 row) postgres=# select statement_timestamp(); statement_timestamp ------------------------------ 2009-02-21 23:35:39.90937+09 (1 row) postgres=# select statement_timestamp(); statement_timestamp ------------------------------- 2009-02-21 23:35:45.633752+09 (1 row) postgres=# select clock_timestamp(); clock_timestamp ------------------------------- 2009-02-21 23:35:52.520483+09 (1 row)
トランザクション内でも、その時点の時刻を取得。
どれを使ったらいいかはよくわからんので、
とりあえず名前だけで clock_timestamp() に決めました。
全部のストアド置き換えなきゃ…
※ちなみに今回はPostgres8.3.5で試してみましたが、
Postgres8.1.xだとstatement_timestamp()やclock_timestamp()が存在しないっぽい…
旧バージョンではどのような代替手段があるんだろう?