Как последовательно отслеживать все новые строки в таблице базы данных SQL - PullRequest
0 голосов
/ 19 марта 2020

Что я пытаюсь сделать

Я занимаюсь разработкой веб-службы, которая работает в нескольких экземплярах сервера, все из которых обращаются к одной и той же СУБД (PostgreSQL). Хотя база данных необходима для постоянства, она содержит очень мало данных, поэтому каждый экземпляр сервера имеет кэш всех данных. Кроме того, приложение действительно простое в том, что оно только когда-либо вставляет новые строки в довольно простые таблицы и выбирает эти данные по расписанию из всех экземпляров сервера (без обновлений или изменений ... только вставки и чтения).

Как это в настоящее время реализовано

В основном у меня есть таблица, которая выглядит примерно так:

id BIGSERIAL,
creation_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- further data columns...

Сервер делает что-то подобное каждые пару секунд (псевдокод):

get all rows with creation_timestamp > lastMaxTimestamp
lastMaxTimestamp = max timestamp for all data just retrieved
insert new rows into application cache

Проблема, с которой я сталкиваюсь

Приложение пропускает определенные строки при обновлении кэшей. Я проанализировал проблему и выяснил, что проблема вызвана следующим образом:

  1. один экземпляр сервера создает новую строку в контексте транзакции. Идентификатор для новой строки извлекается из связанной последовательности (id = n), и устанавливается creation_timestamp (со значением ts_1).
  2. другой сервер делает то же самое в контексте другой транзакции. Новая строка в этой транзакции получает id = n + 1 и creation_timestamp ts_2 (где ts_1
  3. транзакция 2 завершается до транзакции 1
  4. , когда один из серверов выполняет «выбрать все» строки с creation_timestamp> lastMaxTimestamp ". Он получает строку n + 1, но не n1. Он устанавливает для lastMaxTimestamp значение ts_2.
  5. транзакция 1 завершается
  6. , и через некоторое время сервер из шага 4 снова выполняет «выбрать все строки с creation_timestamp> lastMaxTimestamp». Но поскольку lastMaxTimestamp = ts_2 и ts_2> ts_1, строка n никогда не будет считываться на этом сервере.

Примечание: CURRENT_TIMESTAMP имеет одинаковое значение во время транзакции, то есть время начала транзакции.

Таким образом, приложение получает несогласованные данные в свой кэш и не может получать новые строки на основе метки времени вставки ИЛИ на основе идентификатора последовательности. Уровни изоляции транзакций в действительности ничего не меняют в ситуации, так как проблема в сущности создается завершением транзакции 2 до транзакции 1.

Мой вопрос

Я что-то упустил? Я думаю, что должен быть простой способ получить все новые строки СУБД, но я не могу найти простое решение ... по крайней мере, простое решение, которое является последовательным. Обширная блокировка (например, таблиц) не будет приемлемой из-за соображений производительности. Простая попытка обеспечить получение всех идентификаторов из этой последовательности кажется а) сложным решением и б) не может быть легко осуществлена, поскольку могут произойти откаты во время транзакций (что приведет к тому, что идентификаторы последовательности не будут использоваться).

У кого-нибудь есть решение?

1 Ответ

0 голосов
/ 20 марта 2020

После долгих поисков я нашел правильные ключевые слова для google для ... "отметка времени транзакции", чтобы привести ко всем видам отслеживания отметки времени транзакции и системным столбцам, таким как xmin:

https://dba.stackexchange.com/questions/232273/is-there-way-to-get-transaction-commit-timestamp-in-postgres

Этот пост содержит более подробную информацию:

Вопросы по Postgres track_commit_timestamp (pg_xact_commit_timestamp)

Короче:

  • Вы можете включить опцию postgresql, чтобы отслеживать метки времени коммитов и сравнивать их вместо current_timestamps / clock_timestamps внутри транзакции
  • , хотя кажется, что она отслеживается только когда транзакция завершена, а не когда она совершена, что делает решение не пуленепробиваемым. Также есть еще одна проблема, которую следует рассмотреть, например, перенос роли идентификатора транзакции (xmin), например
  • . Логическое декодирование / репликация - это то, что нужно для поиска правильного решения

Спасибо всем, кто пытается помочь я найду ответ. Я надеюсь, что это резюме пригодится кому-то в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...