Откат на основе журнала отката (Undo-based Rewind)
Эта страница переведена при помощи нейросети GigaChat.
OrioleDB предоставляет возможность отката на основе журнала отката (undo), которая позволяет вернуть кластер базы данных к согласованному предыдущему состоянию. В отличие от восстановления до заданного момента времени (Point-in-Time Recovery, PITR), которое опирается на проигрывание журнала предзаписи (Write-Ahead Log, WAL), откат в OrioleDB использует журналы отката (undo logs) для отмены изменений. Данный механизм, как правило, быстрее восстановления на основе WAL для возврата к недавним состояниям базы данных, поскольку напрямую отменяет недавние изменения с использованием цепочки отката.
Для таблиц orioledb откат использует собственные журналы отката движка. Для стандартных таблиц PostgreSQL heap функциональность отката обеспечивается за счет отложенной операции vacuum. Старые версии кортежей сохраняются в куче до тех пор, пока не выйдут за пределы настроенного окна хранения для отката.
Данная функция находится в экспериментальном состоянии и накладывает значительное снижение производительности. По умолчанию она отключена и должна использоваться с осторожностью.
Конфигурация
Следующие параметры управляют подсистемой отката. Они должны быть установлены в postgresql.conf или через ALTER SYSTEM.
| Параметр | Тип | По умолчанию | Диапазон | Описание |
|---|---|---|---|---|
orioledb.enable_rewind | boolean | off | on/off | Включает сбор данных для отката и запускает процесс Rewind Worker |
orioledb.rewind_max_time | integer | 3600 | 1 - 86400 | Максимальный возраст (в секундах), в течение которого запись транзакции сохраняется для отката |
orioledb.rewind_max_transactions | integer | 100000 | 1 - INT_MAX | Максимальное количество транзакций для сохранения в очереди отката |
orioledb.rewind_buffers | integer | 1024 | 6 - INT_MAX | Количество буферов общей памяти для метаданных отката |
Включение отката увеличивает количество фоновых процессов. Необходимо обеспечить, чтобы max_worker_processes был настроен с достаточным запасом для размещения процесса Rewind Worker.
Процесс Rewind Worker
При установке orioledb.enable_rewind в значение on, OrioleDB запускает фоновый процесс Rewind Worker. Данный процесс отвечает за управление жизненным циклом истории транзакций и журналов отката.
Основные обязанности
- Процесс отслеживает очередь отката. Как только транзакция становится старше порога хранения, процесс помечает элемент как завершенный, позволяя системе безопасно удалять старые файлы отката и выполнять очистку мертвых кортежей
heap. - Поддерживает «Горизонт отката» — самую раннюю точку во времени, к которой базу данных можно безопасно вернуть.
- Продолжает обработку очереди с регулярными интервалами даже в периоды неактивности базы данных для предотвращения разрастания хранилища.
Хотя 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()– возвращает самый старый доступныйxidPostgreSQL для отката.orioledb_get_complete_oxid()– возвращает самый старый доступныйoxidOrioleDB для отката.
Операционный рабочий процесс
При вызове функции отката система выполняет следующие шаги:
- Проверяет, что запрошенная цель находится в пределах окна хранения (
rewind_max_time) и чтоorioledb.enable_rewindактивен. - Отправляет сигнал Rewind Worker для прекращения добавления новых транзакций в буфер.
- Отправляет сигнал всем другим активным серверным процессам для завершения. Процесс ожидает до 100 секунд выхода серверных процессов.
- Возвращает страницы данных к запрошенному состоянию.
- После завершения отката, в зависимости от значения аргумента
attempt_restart, функция либо останавливает базу данных, либо пытается перезапустить экземпляр PostgreSQL для завершения изменения состояния.
Автоматический перезапуск выполняется однократно в режиме best-effort. Если перезапуск завершается неудачей (например, из-за ошибок конфигурации), требуется ручное вмешательство для возврата сервера в рабочее состояние. Необходимо обеспечить доступ на уровне системы к серверу для ручного запуска службы, так как SQL-соединение будет немедленно завершено по окончании отката.
Примеры
Для выполнения отката базы данных к состоянию конкретной транзакции необходимо сначала записать идентификаторы транзакций в желаемой «точке восстановления».
- Определить точку восстановления:
-- Записать эти значения
SELECT pg_current_xact_id(), orioledb_get_current_oxid();
pg_current_xact_id | orioledb_get_current_oxid
--------------------+---------------------------
1750 | 555
- Выполнить изменения:
-- Здесь происходит случайная потеря данных или нежелательные изменения
DROP TABLE important_data;
- Выполнить откат:
-- Вернуться к идентификаторам, записанным в шаге 1
SELECT orioledb_rewind_to_transaction(1750, 555);
Сервер выведет в журнал «Rewind complete» и остановится.
Для приложений, требующих строгих гарантий согласованности, рекомендуется явно получать блокировки на соответствующих таблицах внутри транзакции, предназначенной в качестве цели отката. (Шаг 1 в приведенном примере)
Ограничения и предупреждения
- Буфер отката хранится в общей памяти и не является постоянным между перезапусками. Откат к точке времени, предшествующей текущему времени запуска кластера, невозможен.
- Откат разрушает все изменения данных, произошедшие после целевой точки. Рекомендуется создать резервную копию перед инициированием отката.
- Поскольку откат требует сохранения старых версий в таблицах
heap, стандартная очистка vacuum подавляется для данных в пределах окна отката. Высокий объем записи в таблицыheapможет привести к значительному разрастанию. - Откат в настоящее время несовместим с физической репликацией. Серверы standby не отражают операцию отката и станут несогласованными с основным сервером.
- Если система аварийно завершает работу или прерывается во время фазы отката, база данных может оказаться в несогласованном состоянии.