Мне нужно реализовать синхронизацию данных в распределённой системе, учитывая, что в таблицы с данными происходит конкурентная запись. Экспорт из основной БД должен читать только изменённые (и вставленные) строки.
Обычный совет в таком случае: "используй триггеры", помечай в триггере строки timestamp'ом изменения данных или монотонно возрастающей числовой последовательностью (ревизией). И сообщай удалённой системе этот timestamp/ревизию.
Но проблема с конкурентной записью в том, когда происходит коммит. Ниже описан пример:
[время 00:00] Транзакция A начинает запись большой пачки данных; помечает строки timestamp [00:00].
[время 00:02] Транзакция B начинает запись маленькой пачки данных; помещает строки timestamp [00:02].
[время 00:03] Транзакция B заканчивает запись и происходит коммит.
[время 00:10] Начинается экспорт в удалённую систему. Уровень изоляции - ReadCommitted,
поэтому только данные из транзакции B попадают в выборку для экспорта, timestamp 00:02.
[время 00:15] Транзакция A заканчивает запись и происходит коммит.
Удалённая система никогда не получит эти данные(!)
Я хочу, чтобы строки из Транзакции А были в БД помечены как более поздние, чем строки в Транзакции B.
Ведь закоммитились они позже: доказательство тому - в момент экспорта по факту в БД их ещё не было (как раз благодаря изоляции).
Мне нравится подход с
Change tracking в MSSQL, он эту ситуация способен решить.
Но я держу в голову скорый переход на PostgreSQL, и мне нужно придумать общее решение.
Как правильно решать подобную задачу?
Оригинал моего
вопроса на StackOverflow - здесь.