Go + PostgreSQL: почему NOW() врёт о времени выполнения ⏱️

Представим обычный go-сервис, который обрабатывает заказ в транзакции PostgreSQL.

Кажется логичным ожидать, что updated_at будет примерно на пять секунд позже created_at.

Но это не так. В PostgreSQL NOW() возвращает время начала текущей транзакции. Значение не меняется, даже если внутри транзакции прошло несколько секунд или минут. В результате created_at и updated_at могут оказаться одинаковыми. Как исправить?

Всё зависит от того, какое именно время нам нужно.

- Время начала текущей транзакции SELECT NOW(); - Время начала выполнения текущего SQL-запроса SELECT statement_timestamp(); - Фактическое текущее время

SELECT clock_timestamp();

Если updated_at должен отражать фактический момент выполнения обновления, можно использовать:

UPDATE orders SET status = $1, updated_at = clock_timestamp() WHERE id = $2;

При этом NOW() не сломан. Его поведение полезно, когда все изменения одной транзакции должны иметь согласованную временную отметку. Что важно помнить в go?

Если транзакция включает несколько запросов, длительную обработку или ожидание других операций, не стоит автоматически считать NOW() временем выполнения конкретного запроса.

Сначала определите семантику поля: created_at для единого времени создания в рамках транзакции часто подходит NOW().

updated_at для фактического момента обновления может требовать clock_timestamp().

Для времени начала каждого sql-запроса подходит statement_timestamp(). Небольшой нюанс, который легко пропустить, а потом долго искать причину одинаковых временных меток в логах и таблицах.

Go + PostgreSQL: почему NOW() врёт о времени выполнения ⏱️ | Сетка — социальная сеть от hh.ru