Перейти к основному содержимому

Откат на основе журнала отката (Undo-based Rewind)

примечание

Эта страница переведена при помощи нейросети GigaChat.

OrioleDB предоставляет возможность отката на основе журнала отката (undo), которая позволяет вернуть кластер базы данных к согласованному предыдущему состоянию. В отличие от восстановления до заданного момента времени (Point-in-Time Recovery, PITR), которое опирается на проигрывание журнала предзаписи (Write-Ahead Log, WAL), откат в OrioleDB использует журналы отката (undo logs) для отмены изменений. Данный механизм, как правило, быстрее восстановления на основе WAL для возврата к недавним состояниям базы данных, поскольку напрямую отменяет недавние изменения с использованием цепочки отката.

Для таблиц orioledb откат использует собственные журналы отката движка. Для стандартных таблиц PostgreSQL heap функциональность отката обеспечивается за счет отложенной операции vacuum. Старые версии кортежей сохраняются в куче до тех пор, пока не выйдут за пределы настроенного окна хранения для отката.

warning

Данная функция находится в экспериментальном состоянии и накладывает значительное снижение производительности. По умолчанию она отключена и должна использоваться с осторожностью.

Конфигурация

Следующие параметры управляют подсистемой отката. Они должны быть установлены в postgresql.conf или через ALTER SYSTEM.

ПараметрТипПо умолчаниюДиапазонОписание
orioledb.enable_rewindbooleanoffon/offВключает сбор данных для отката и запускает процесс Rewind Worker
orioledb.rewind_max_timeinteger36001 - 86400Максимальный возраст (в секундах), в течение которого запись транзакции сохраняется для отката
orioledb.rewind_max_transactionsinteger1000001 - INT_MAXМаксимальное количество транзакций для сохранения в очереди отката
orioledb.rewind_buffersinteger10246 - INT_MAXКоличество буферов общей памяти для метаданных отката
примечание

Включение отката увеличивает количество фоновых процессов. Необходимо обеспечить, чтобы max_worker_processes был настроен с достаточным запасом для размещения процесса Rewind Worker.

Процесс Rewind Worker

При установке orioledb.enable_rewind в значение on, OrioleDB запускает фоновый процесс Rewind Worker. Данный процесс отвечает за управление жизненным циклом истории транзакций и журналов отката.

Основные обязанности

  • Процесс отслеживает очередь отката. Как только транзакция становится старше порога хранения, процесс помечает элемент как завершенный, позволяя системе безопасно удалять старые файлы отката и выполнять очистку мертвых кортежей heap.
  • Поддерживает «Горизонт отката» — самую раннюю точку во времени, к которой базу данных можно безопасно вернуть.
  • Продолжает обработку очереди с регулярными интервалами даже в периоды неактивности базы данных для предотвращения разрастания хранилища.
warning

Хотя Rewind Worker управляет своим «списком задач» в кольцевом буфере фиксированного размера, отсутствие прогресса вызывает два основных побочных эффекта на здоровье системы:

  • Если процесс отстает, OrioleDB не может освободить место в физических журналах отката (Undo Logs). Эти журналы переполняются из памяти в каталог orioledb_undo на диске, вызывая его неограниченный рост до тех пор, пока процесс не догонит.
  • Процесс отвечает за продвижение глобального горизонта xmin. Если процесс застревает на старой транзакции, PostgreSQL и OrioleDB считают все последующие версии строк «потенциально необходимыми». Это препятствует удалению мертвых кортежей операцией VACUUM, приводя к значительному разрастанию таблиц и деградации производительности запросов.

Функции отката

orioledb_rewind_by_time(seconds int4[, attempt_restart bool])

Выполняет откат состояния кластера на указанное количество секунд от текущего времени.

  • Параметры:

    • seconds – количество секунд для отката состояния кластера.
    • attempt_restart – если true, система базы данных автоматически перезапустится после отката. Если false, база данных будет только остановлена. По умолчанию false.
  • Примеры:

    • SELECT orioledb_rewind_by_time(600); — откат на 10 минут и остановка базы данных без перезапуска.
    • SELECT orioledb_rewind_by_time(600, true); — откат на 10 минут и перезапуск базы данных.

orioledb_rewind_to_timestamp(target_time timestamptz[, attempt_restart bool])

Выполняет откат кластера к конкретной точке во времени.

  • Параметры:

    • target_time – точная метка времени, к которой будет восстановлено состояние кластера.
    • attempt_restart – если true, система базы данных автоматически перезапустится после отката. Если false, база данных будет только остановлена. По умолчанию false.
  • Примеры:

    • SELECT orioledb_rewind_to_timestamp('2025-01-01 12:00:00 UTC', true); — откат к 1 января 2025 года, 12:00:00 UTC, и перезапуск базы данных.
    • SELECT orioledb_rewind_to_timestamp('2025-01-01 12:00:00 UTC'); — откат к указанной метке времени и остановка базы данных без перезапуска.

orioledb_rewind_to_transaction(xid int4, oxid int8[, attempt_restart bool])

Выполняет откат кластера к состоянию перед конкретной парой транзакций, идентифицированной идентификатором транзакции PostgreSQL (xid) и идентификатором транзакции OrioleDB (oxid).

  • Параметры:

    • xid – идентификатор транзакции PostgreSQL.
    • oxid – идентификатор транзакции OrioleDB.
    • attempt_restart – если true, система базы данных автоматически перезапустится после отката. Если false, база данных будет только остановлена. По умолчанию false.
  • Примеры:

    • SELECT orioledb_rewind_to_transaction(1750, 555, true); — откат состояния кластера к моменту, непосредственно перед парой транзакций 1750/555, и перезапуск базы данных.
    • SELECT orioledb_rewind_to_transaction(1750, 555); — откат состояния кластера к моменту, непосредственно перед указанной парой транзакций, и остановка базы данных без перезапуска.

Проверка горизонта отката

Для проверки доступного диапазона отката использовать:

  • orioledb_get_current_oxid() – возвращает идентификатор текущей транзакции OrioleDB. Назначает новый, если текущая транзакция еще не имеет идентификатора.
  • orioledb_get_complete_xid() – возвращает самый старый доступный xid PostgreSQL для отката.
  • orioledb_get_complete_oxid() – возвращает самый старый доступный oxid OrioleDB для отката.

Операционный рабочий процесс

При вызове функции отката система выполняет следующие шаги:

  1. Проверяет, что запрошенная цель находится в пределах окна хранения (rewind_max_time) и что orioledb.enable_rewind активен.
  2. Отправляет сигнал Rewind Worker для прекращения добавления новых транзакций в буфер.
  3. Отправляет сигнал всем другим активным серверным процессам для завершения. Процесс ожидает до 100 секунд выхода серверных процессов.
  4. Возвращает страницы данных к запрошенному состоянию.
  5. После завершения отката, в зависимости от значения аргумента attempt_restart, функция либо останавливает базу данных, либо пытается перезапустить экземпляр PostgreSQL для завершения изменения состояния.
warning

Автоматический перезапуск выполняется однократно в режиме best-effort. Если перезапуск завершается неудачей (например, из-за ошибок конфигурации), требуется ручное вмешательство для возврата сервера в рабочее состояние. Необходимо обеспечить доступ на уровне системы к серверу для ручного запуска службы, так как SQL-соединение будет немедленно завершено по окончании отката.

Примеры

Для выполнения отката базы данных к состоянию конкретной транзакции необходимо сначала записать идентификаторы транзакций в желаемой «точке восстановления».

  1. Определить точку восстановления:
-- Записать эти значения
SELECT pg_current_xact_id(), orioledb_get_current_oxid();

pg_current_xact_id | orioledb_get_current_oxid
--------------------+---------------------------
1750 | 555
  1. Выполнить изменения:
-- Здесь происходит случайная потеря данных или нежелательные изменения
DROP TABLE important_data;
  1. Выполнить откат:
-- Вернуться к идентификаторам, записанным в шаге 1
SELECT orioledb_rewind_to_transaction(1750, 555);

Сервер выведет в журнал «Rewind complete» и остановится.

примечание

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

Ограничения и предупреждения

  • Буфер отката хранится в общей памяти и не является постоянным между перезапусками. Откат к точке времени, предшествующей текущему времени запуска кластера, невозможен.
  • Откат разрушает все изменения данных, произошедшие после целевой точки. Рекомендуется создать резервную копию перед инициированием отката.
  • Поскольку откат требует сохранения старых версий в таблицах heap, стандартная очистка vacuum подавляется для данных в пределах окна отката. Высокий объем записи в таблицы heap может привести к значительному разрастанию.
  • Откат в настоящее время несовместим с физической репликацией. Серверы standby не отражают операцию отката и станут несогласованными с основным сервером.
  • Если система аварийно завершает работу или прерывается во время фазы отката, база данных может оказаться в несогласованном состоянии.