Image
Резервное копирование
Базовая резервная копия
16
Авторские права
© Postgres Professional, 2017–2025
Авторы: Егор Рогов, Павел Лузанов, Илья Баштанов, Алексей Береснев
Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
Использование материалов курса
Некоммерческое использование материалов курса (презентации,
демонстрации) разрешается без ограничений. Коммерческое
использование возможно только с письменного разрешения компании
Postgres Professional. Запрещается внесение изменений в материалы
курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу:
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за
любые повреждения и убытки, включая потерю дохода, нанесенные
прямым или непрямым, специальным или случайным использованием
материалов курса. Компания Postgres Professional не предоставляет
каких-либо гарантий на материалы курса. Материалы курса
предоставляются на основе принципа «как есть» и компания Postgres
Professional не обязана предоставлять сопровождение, поддержку,
обновления, расширения и изменения.
Image
2
Темы
Понятие физической резервной копии
Холодное и горячее резервирование
Протокол репликации и слот
Клонирование кластера и архивная копия
Проверка целостности
API резервирования
Image
3
Физическая копия
Базовая физическая копия — копия всех файлов кластера
+ быстрее, чем логическое резервирование
+ восстанавливается статистика
− можно восстановиться только на совместимой системе
и на той же самой основной версии PostgreSQL
− выборочная копия невозможна, копируется весь кластер
Физическое резервирование подразумевает копирование всех файлов,
относящихся к кластеру БД (как файлов данных, так и служебных
файлов), то есть создание полной двоичной копии.
Копирование файлов работает быстрее, чем выгрузка SQL-команд
при логическом резервировании; запустить сервер из созданной
физической копии — дело нескольких минут, в отличие от
восстановления из логической копии. Кроме того, нет необходимости
заново собирать статистику — она также восстанавливается из копии.
Но есть и минусы. Из физической резервной копии можно восстановить
систему только на совместимой платформе (та же ОС, та же
разрядность, тот же порядок байтов в представлении чисел и т. п.)
и только на той же основной версии PostgreSQL. Кроме того,
невозможно сделать физическую копию отдельных баз данных
кластера, возможно копирование только всего кластера целиком.
Image
4
Холодное резервирование
Выключенный сервер
если выполнена контрольная точка, то достаточно скопировать файлы
копию можно развернуть на другом сервере, независимо от PGDATA
+ простота
− требуется прерывание обслуживания
Снимок файловой системы
как при неаккуратном выключении: при старте потребуется
восстановление, но в копию войдут все нужные файлы журнала
данные, в т. ч. табличные пространства, должны войти в один снимок
+ не надо останавливать сервер
− файловые системы, поддерживающие снимки, работают медленней
Смысл холодного резервирования состоит в том, чтобы сделать копию
файлов кластера в тот момент, когда данные на диске согласованы,
то есть на диск сброшено актуальное состояние всех страниц.
Восстановление из такой копии происходит просто: файлы
разворачиваются, запускается сервер — и он сразу же готов к работе.
Сделать такую копию можно лишь корректно остановив сервер
с выполнением контрольной точки. Минус понятен: необходима
остановка сервера (надолго при большом объеме данных).
Время простоя можно сократить за счет предварительного выполнения
rsync (или аналогичного инструмента) при работающем сервере. Тогда
после останова сервера rsync докопирует только изменения (которых,
предположительно, будет немного). Но простоя все равно не избежать.
Другой вариант — сделать несогласованную копию, в которую попадут
страницы, сохраненные в разное время. Такая рассогласованность
неизбежна при некорректном отключении сервера или при создании
снимка файловой системы. В последнем случае все файлы кластера
должны попасть в один снимок. Это может оказаться невозможным,
если файлы расположены в разных файловых системах.
При восстановлении из несогласованных данных серверу при старте
потребуется согласовать страницы. Это обычная автоматическая
процедура восстановления после сбоя. Она не представляет проблемы,
так как необходимые файлы журнала гарантированно попадут в копию,
но потребует некоторого времени.
Image
6
Горячее резервирование
Работающий сервер
страницы не согласованы между собой, как при неаккуратном
выключении
страница может меняться во время ее копирования
(проблема неатомарного чтения и записи)
для восстановления согласованности необходимы журнальные записи
от последней контрольной точки за все время копирования
(в процессе копирования сервер может удалить часть файлов)
+ не требуется прерывание обслуживания
− нужны специальные инструменты
Горячее резервирование выполняется на работающем сервере,
поэтому в копию наверняка попадут несогласованные между собой
страницы.
Более того. При резервном копировании данные читаются не через
буферный кеш, а напрямую из файлов. Содержимое файлов на диске,
очевидно, изменяется во время копирования, а гарантии атомарности
чтения/записи страниц PostgreSQL может и не быть (это зависит от
файловой системы и оборудования и обсуждается в теме «Настройка
журнала» курса DBA2). Поэтому в резервную копию могут попадать
«безнадежные» страницы, к которым даже нельзя применить
журнальные записи. Это первая сложность.
Вторая сложность состоит в том, что копирование файлов данных
может занимать достаточно много времени. Но сервер, после
выполнения очередной контрольной точки, может удалить часть
файлов журнала, которые уже не нужны ему для восстановления после
сбоя, но нужны для резервной копии.
Если не принять специальных мер, сделанная резервная копия будет
непригодна для восстановления. Поэтому для горячего резервирования
требуются специальные инструменты. PostgreSQL предоставляет
низкоуровневый интерфейс, используя который можно реализовать
надежное копирование. Этот интерфейс использует и штатная утилита
pg_basebackup, и другие сторонние средства резервного копирования.
Image
7
Протокол репликации
Задачи
управление резервным копированием и репликацией
в частности, получение потока журнальных записей
Обслуживается процессом wal sender
max_wal_senders = 10
wal_level = replica или logical, но не minimal
Подключение
роль с атрибутом REPLICATION или SUPERUSER
разрешение на подключение в pg_hba.conf
Для упрощения задачи сервер PostgreSQL предоставляет протокол
репликации — специальный протокол для управления как собственно
репликацией (рассматривается в одноименном модуле), так и
резервным копированием. В частности, он позволяет получать поток
журнальных записей, которые генерирует сервер.
На сервере подключение по протоколу репликации обслуживается
процессом wal sender. Он похож на обычный обслуживающий процесс,
который запускается при обычном подключении клиента, но понимает
не SQL, а специальные команды. Число одновременно работающих
процессов wal_sender ограничено параметром max_wal_senders
(значение по умолчанию — 10).
Уровень журнала должен быть не ниже, чем replica. Дело в том, что
на уровне minimal такие команды, как CREATE TABLE AS SELECT,
CREATE INDEX или COPY FROM не попадают в журнал: долговечность
обеспечивается тем, что данные не остаются в оперативной памяти,
а сразу записываются на диск. Этого достаточно для восстановления
после сбоя и из холодной копии, но недостаточно для восстановления
из горячей копии.
Чтобы использовать протокол репликации, клиент должен
подключаться к серверу под ролью, имеющей атрибут REPLICATION
(либо под суперпользователем). В pg_hba.conf надо разрешить
подключение этой роли к базе данных replication (это не название БД,
а ключевое слово). Причем разрешения для all недостаточно,
подключение к replication должно быть разрешено отдельно.
Image
8
Слот репликации
Серверный объект для гарантии получения журнальных
записей
помнит, какая запись была передана клиенту последней
число слотов ограничено max_replication_slots = 10
Не позволяет удалить сегмент WAL,
пока все его записи не переданы клиенту
клиент может получать данные в удобном режиме,
в том числе отключаться на время
при отключении клиента журнальные файлы накапливаются на сервере
мониторинг состояния: pg_replication_slots
Чтобы при выполнении контрольной точки сервер не удалил файлы
WAL преждевременно, можно применять слот репликации. Если поток
журнальных записей идет через слот, то слот помнит, какие записи уже
были переданы клиенту, и не позволяет серверу удалять файл WAL
до тех пор, пока клиент не получит все записи из этого файла.
Использование слота позволяет клиенту не беспокоиться о том, что
сервер сотрет файл журнала раньше времени. Клиент даже может
отключиться и затем через какое-то время подключиться вновь и
продолжить получать журнальные записи с того момента, на котором
остановился.
Но надо иметь в виду, что при отключении клиента файлы журнала
будут накапливаться на сервере и могут занять все свободное место.
Поэтому каждый созданный слот следует добавлять в мониторинг
(представление pg_replication_slots) и своевременно удалять ненужные
слоты.
Общее количество слотов, которые могут быть созданы, ограничено
конфигурационным параметром max_replication_slots (значение
по умолчанию — 10).
Подробнее применение слотов обсуждается в модуле «Репликация».
Image
9
для физического копирования используется утилита pg_basebackup
после копирования новый сервер готов к запуску
Клонирование кластера
pg_wal
сервер базовая копия
pg_global
pg_default
TS
--waldir
--wal-method=stream
--tablespace-mapping
pg_global
pg_default
TS
--pgdata
pg_basebackup
wal senderwal sender
--compress=server-*
(gzip, lz4, zstd)
--format=plain
Для немедленного развертывания нового сервера из копии вызывают
pg_basebackup в обычном формате (--format=plain по умолчанию),
запуская утилиту на целевом сервере. Она подключается к серверу-
источнику и копирует с него файлы в локальный каталог, указанный
параметром --pgdata.
Дополнительные табличные пространства копируются по тем же
абсолютным путям, что и на сервере-источнике. Пути можно
переназначить, указав соответствия в параметрах --tablespace-mapping
утилиты. Это необходимо, если pg_basebackup запускается на самом
сервере-источнике.
При потоковой доставке (--wal-method=stream по умолчанию) утилита
устанавливает второе соединение для передачи потока журнальных
записей, которые генерирует работающий сервер, в локальный каталог,
указанный параметром --waldir.
По умолчанию второе соединение использует временный слот
репликации, который создается при подключении и удаляется при
завершении работы pg_basebackup. Однако можно указать и имя
постоянного слота, который должен существовать на момент запуска
утилиты или создаваться ей.
В формате plain можно сжимать данные на сервере, уменьшая нагрузку
на сеть. Переданные данные затем распаковываются утилитой. Но
журнальные записи в потоковом режиме не сжимаются.
Image
11
Проверка целостности
Проверка файлов данных
задача: гарантировать, что в копию попадут целостные данные
утилиты pg_basebackup и pg_checksums
проверяют контрольные суммы страниц файлов отношений
Проверка резервной копии
задача: проверить, что целостность данных в копии
не нарушилась со временем
файл манифеста backup_manifest
утилита pg_verifybackup проверяет файлы по списку из манифеста
Данные могут повреждаться как при записи на носитель, так
и в процессе хранения. Важно убедиться в том, что в копию попали
целостные данные и в дальнейшем эта целостность не нарушилась.
Расчет контрольных сумм файлов отношений включается при
инициализации кластера (или в процессе работы утилитой
pg_checksums). Контрольная сумма сохраняется при каждом изменении
страницы в ее заголовке. Вычисленная и сохраненная контрольная
сумма сравниваются:
при каждом чтении страницы в буферный кеш;
утилитой pg_basebackup при формировании резервной копии;
утилитой pg_checksums в режиме проверки.
Утилита pg_basebackup включает в копию файл backup_manifest
с информацией о файлах (имена, размеры, вычисленные контрольные
суммы) и журнальных записях (начальная и конечная позиции WAL,
линия времени), а также контрольную сумму самого манифеста.
Утилита pg_verifybackup проверяет соответствие резервной копии
манифесту: наличие файлов, корректность контрольных сумм,
возможность чтения и разбора записей WAL, необходимых для
восстановления.
Для полной уверенности все же следует развернуть резервную копию
и проверить работоспособность сервера, ведь совпадение контрольных
сумм не дает гарантии, что данные не были повреждены.
Image
13
создание копии для будущего использования
Потоковая доставка WAL
pg_wal
сервер
pg_global
pg_default
TS
pg_basebackup
wal senderwal sender
--compress=server-*
--format=tar
OID.tar
base.tar
pg_wal.tar
--compress=client-*
клиент
--pgdata
--wal-method=stream
Для создания архивных копий используется формат tar. По умолчанию
используется потоковая доставка журнальных записей (параметр
--wal-method=stream).
Файлы кластера будут сохранены в файле base.tar. Каждое
дополнительное табличное пространство копируется в отдельный tar-
файл, имя которого совпадает с OID табличного пространства.
Сегменты WAL помещаются в отдельный файл pg_wal.tar.
Утилита может выполнять сжатие как на стороне клиента, так и на
стороне сервера (в последнем случае pg_wal.tar не сжимается).
К именам сжатых tar-архивов добавится суффикс, соответствующий
методу сжатия. Например, при сжатии методом gzip основной файл
будет называться base.tar.gz.
Для восстановления из такой копии сначала потребуется развернуть
tar-файлы по правильным путям. При этом пути табличных пространств
можно изменить: для этого нужно перед запуском сервера
отредактировать файл tablespace_map или использовать параметр
командной строки --tablespace-mapping.
Image
14
создание копии для будущего использования
Файловая доставка клиенту
pg_wal
сервер
pg_global
pg_default
TS
pg_basebackup
wal sender
--compress=server-*
OID.tar
--compress=client-*
клиент
--pgdata
base.tar
--wal-method=fetch
--format=tar
При создании архивной копии можно использовать другой режим —
файловую доставку журнальных записей (--wal-method=fetch).
В этом случае отдельное соединение не создается, а сегменты журнала
копируются и передаются по основному соединению. Это происходит
после того, как скопированы все файлы кластера. Необходимо
учитывать, что во время контрольной точки сервер может удалить
сегменты журнала, уже не нужные для восстановления, поэтому стоит
позаботиться об их сохранности, установив достаточно большое
значение параметру wal_keep_size.
Журнальные сегменты записываются в файл base.tar вместе
с остальными файлами кластера.
В большинстве случаев возможность использовать режим fetch при
создании копии на клиенте не нужна. Она осталась с прежних версий
и в настоящее время может иметь смысл только для того, чтобы
передавать журнальные записи сжатыми — режим stream не дает такой
возможности.
Image
16
создание копии для будущего использования
копия создается на сервере без передачи данных по сети
Файловая доставка серверу
--wal-method=fetch
--target=server:path
path
pg_wal
pg_global
pg_default
TS
pg_basebackup
wal sender
OID.tar
base.tar
--compress=server-*
сервер
клиент
Архивную копию можно создать на сервере, запуская pg_basebackup
на клиенте. Данные при этом не передаются по сети.
Создание копии на сервере задается параметром командной строки
pg_basebackup --target=server:path, где path путь к каталогу
в файловой системе сервера (по умолчанию подразумевается
--target=client).
В этом режиме также можно использовать сжатие, но, конечно, только
на стороне сервера.
При создании копии на сервере невозможно использовать потоковый
режим доставки WAL (stream), поскольку журнальные записи вообще
не передаются клиенту. Необходимо указать режим доставки fetch, при
котором накопившиеся журнальные сегменты копируются и
помещаются в файл base.tar вместе с остальными файлами кластера.
Image
18
на время копирования устанавливается full_page_writes = on
в самом начале выполняется контрольная точка (быстро или обычно)
Низкоуровневый взгляд
время
контрольная точка
контрольная точка
копирование файлов данных
начало
копирования
контрольная точка
конец
копирования
необходимые файлы журнала
для борьбы
с неатомарностью
чтения и записи
Общий алгоритм изготовления резервной копии на низком уровне
одинаков как для pg_basebackup, так и для любых сторонних средств
(которые могут потребоваться, поскольку pg_basebackup предоставляет
только самую базовую функциональность).
1. Надо сообщить серверу о том, что начинается резервное
копирование.
При этом, во-первых, на время копирования устанавливается параметр
full_page_writes: при первом изменении страницы после контрольной
точки полный образ этой страницы записывается в журнал.
При восстановлении журнальные записи будут применяться не
к страницам в файле (из-за неатомарности ввода-вывода части
страницы могут оказаться рассогласованными), а к образу страницы
из журнала.
Во-вторых, выполняется контрольная точка. Предусмотрено два
режима: быстрое выполнение (что может привести к пиковой нагрузке
на дисковую подсистему) и протяженное (которое определяется
обычным параметром checkpoint_completion_target).
2. После прохождения контрольной точки можно копировать файлы
данных любым удобным способом.
3. После того, как все скопировано, надо сообщить серверу, что
резервное копирование завершено.
4. Кроме того, так или иначе надо обеспечить попадание в резервную
копию всех журнальных записей, сгенерированных с начала
копирования и до его окончания.
Image
19
API резервирования
Начало копирования: pg_backup_start
выполняет контрольную точку, устанавливает full_page_writes
возвращает начальную позицию в журнале
Конец копирования: pg_backup_stop
возвращает конечную позицию в журнале
Копирование файлов
либо протокол репликации, либо любые средства ОС
Копирование журнала от начальной до конечной позиции
протокол репликации + слот либо средства ОС + wal_keep_size
Описанный алгоритм резервного копирования можно использовать,
чтобы реализовать свою собственную утилиту копирования.
Резервное копирование начинается вызовом функции pg_backup_start.
Она устанавливает параметр full_page_writes и выполняет контрольную
точку, как рассматривалось выше. Возвращаемое этой функцией
значение — позиция в журнале, начиная с которой в копию должны
попасть журнальные записи.
В конце копирования вызывается функция pg_backup_stop. Она
возвращает конечную позицию в журнале.
Все журнальные записи между начальной и конечной позициями надо
поместить в резервную копию. Поскольку при своей работе сервер
может удалять журнальные файлы, которые не требуются для
восстановления, надо либо пользоваться протоколом репликации
и слотом, получая записи во время копирования (как pg_basebackup
в режиме доставки --wal-method=stream), либо — что менее удобно
копировать файлы средствами ОС, установив параметр wal_keep_size.
Можно копировать файлы в несколько потоков, использовать rsync
и т. п.
Image
20
Итоги
Базовая резервная копия —
полная копия кластера, включая табличные пространства,
плюс журнал для восстановления согласованности
Горячее резервирование позволяет не останавливать сервер
Инструменты
протокол репликации
слот репликации
низкоуровневый API резервирования
Image
21
Практика
1. В первом кластере создайте табличное пространство
и базу данных с таблицей в этом пространстве.
2. Сделайте базовую резервную копию кластера с помощью
pg_basebackup в формате tar со сжатием.
3. Разверните второй кластер из этой резервной копии.
Табличное пространство разместите в другом каталоге,
изменив файл tablespace_map.
4. Запустите второй сервер и проверьте его работоспособность.
После выполнения практики удалите базу данных и табличное
пространство в обоих кластерах.
Image
22
Практика+
1. Подключите модуль basebackup_to_shell для создания
базовой резервной копии на сервере с помощью
определяемой пользователем команды. Эта команда должна
сжимать tar-архив копии утилитой bzip2.
2. Выполните резервное копирование на сервере в формате tar.
Убедитесь, что полученный архив сжат bzip2.
3. Восстановите кластер beta из полученного сжатого архива
и проверьте его работоспособность.
1. Для подключения модуля укажите одноименную библиотеку
в параметре shared_preload_libraries. Параметром
basebackup_to_shell.command задайте команду, выполняемую при
резервном копировании:
bzip2 -c > архив.tar.bz2
2. Чтобы задействовать модуль при резервном копировании, укажите
pg_basebackup --target=shell
3. Для извлечения файлов из сжатого утилитой bzip2 архива tar
воспользуйтесь командой:
tar xjf архив.tar.bz2 -C каталог-назначения
После выполнения практики удалите созданные базы данных и
резервную копию.
Image