Postgres NOW (): это может быть в прошлом? - PullRequest
0 голосов
/ 17 июня 2020

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

SELECT * FROM my_table
WHERE last_updated < NOW()

, который возвращает одну строку с last_updated, соответствующим 10:10:10. Означает ли это, что невозможно добавить другую строку с last_updated, соответствующим 10:10:09? Если это может произойти в некоторых случаях, есть ли способ сделать это невозможным / снизить риск?

Контекст: конечная точка HTTP, которая используется в качестве цели опроса для последних обновлений. Это зависит от свойства, где, если строки возвращаются из запроса с определенным last_updated разом, то, чтобы гарантировать, что обновления не пропущены, другие изменения должны иметь свое last_updated время после всех возвращенные строки.

Фактический запрос больше похож на приведенный ниже. Если последний элемент в результате опроса имел временную метку last_updated из 1575452913 и id из 123, то следующий опрос будет выглядеть примерно так, как показано ниже.

SELECT * FROM my_table
WHERE (last_updated, id) > (1575452913, 123) AND last_updated < EXTRACT(EPOCH FROM NOW())
ORDER BY (last_updated, id)
LIMIT 500

> в приведенном выше примере возникает состояние гонки. Если строки были добавлены с last_updated из перед 1575452913, то они будут пропущены.

What I думаю, Я хочу, это вместо NOW() какая-то функция, которая возвращает самое раннее NOW() время всех открытых транзакций?

last_updated < EARLIEST_NOW_OF_OPEN_TRANSACTIONS()

Я понимаю, что это очень похожая ситуация на https://timerwich.com/posts/2018/01/29/monotonically-increasing-ids-in-postgres/. Они хотят гарантировать монотонно увеличивающиеся идентификаторы, а я хочу то же самое, но с отметками времени. Ах: и теперь я вижу https://github.com/cockroachdb/cockroach/issues/9227, в котором обсуждаются аналогичные проблемы, хотя и для другой базы данных.

1 Ответ

3 голосов
/ 17 июня 2020

NOW() возвращает дату начала текущей транзакции. Поэтому, если другая транзакция началась раньше, NOW() может вернуть более раннюю дату.

Вы можете использовать вместо clock_timestamp().

См. Подробности в Функции даты / времени .

...