Аналитика
Является ли pg_dump инструментом резервного копирования?

Является ли pg_dump инструментом резервного копирования?

Перевод заметки "Is pg_dump a Backup Tool?"

В последнее время я часто слышу, как опытные пользователи PostgreSQL говорят: «pg_dump не является инструментом резервного копирования». На самом деле, к всеобщему облегчению, документация недавно была обновлена: заменили "backup" на "export". Теперь не говорится, что это инструмент резервного копирования. Опытные пользователи и разработчики PostgreSQL были публично осуждены за смелость утверждать, что pg_dump, по сути, является инструментом резервного копирования. Я нахожу эту историю глубоко разочаровывающей по двум причинам.

Первая причина (менее важная из двух) заключается в том, что фактически pg_dump был командой для бекапа. До 31 июля 2024 года документация описывала pg_dump как инструмент резервного копирования в течение очень долгого времени. Формулировка, о которой идет речь, была добавлена 17 апреля 2003 года. Справедливости ради стоит отметить, что тот факт, что документация говорит о чем-то на протяжении 20 с лишним лет, не делает это автоматически правдой. Но факт остается фактом: если вы правильно используете pg_dump и pg_dumpall, вы можете сохранить все данные вашей базы данных и загрузить их в новую базу данных потом. И до того, как я стал хакером PostgreSQL, я делал именно это в течение многих лет, и это отлично работало для меня. Если по случайности моя база данных выходила из строя и я терял содержимое каталога данных, я мог восстановить ее из одного из сохраненных дампов и получить резервную копию системы.

Знаете, как я называю систему, которая позволяет восстановить данные и вернуться в исходное состояние в случае катастрофы? Правильно: я называю ее инструментом резервного копирования.

Это не значит, что я особо рекомендую такой подход для типичного пользователя. В то время я работал с очень маленькими базами данных PostgreSQL с небольшим количеством пользователей и небольшим объемом данных, даже по стандартам того времени. Резервное копирование больших баз данных с помощью pg_dump может быть очень медленным, и их восстановление также. Поскольку pg_dump хранит снимок MVCC во время работы, длительное резервное копирование может стать проблемой не только с точки зрения использования ресурсов, но и потому, что может привести к раздуванию базы данных, которую впоследствии придется очищать с помощью VACUUM или, если дела пойдут совсем плохо, даже с помощью VACUUM FULL. Что совсем не весело.

Кроме того, я был (по крайней мере, по моему собственному мнению) очень искушенным пользователем, готовым устранять любые проблемы вручную, и иногда мне приходилось это делать. Например, если вы используете pg_dump для создания дампа, а затем пытаетесь восстановить этот дамп на более новой версии базы данных, вы можете получить ошибки. Если вы делаете дамп с помощью версии pg_dump, соответствующей версии сервера, на котором вы собираетесь восстанавливать базу данных, такой проблемы возникнуть не должно. Но если вы пытаетесь восстановить существующий, более старый дамп на новой версии, могут быть проблемы. Иногда я попадал в такую ситуацию, и мне приходилось вручную корректировать дамп, чтобы он восстановился.

Кроме того, если вы используете pg_dump, вам нужно запустить ero для каждой базы данных отдельно, плюс pg_dumpall -g для сохранения всех ваших глобальных данных, плюс резервное копирование всех конфигурационных файлов, таких как pg_hba.conf или postgresql.conf, которые не сохраняются ни pg_dump, ни pg_dumpall. Если вы не знаете, что делаете, это чревато ошибками.

В этом кроется еще одна слабость подхода pg_dump, которая заключается в том, что pg_dump, как и pg_basebackup, не окажет вам никакой помощи в организации резервного копирования. Если вы хотите сохранить, например, N последних резервных копий, pg_dump вам не помощник. Когда вам нужно восстановить глобальные объекты (из pg_dumpall -g), а затем все объекты отдельных баз данных (из pg_dump для каждой отдельной базы данных), эти утилиты не помогут сделать все это в правильном порядке или с нужным количеством параллелизма, так же как и не помогут решить, в каком формате делать дамп: в tar или в пользовательском. Все это вы должны решить сами.

По всем этим причинам и, возможно, по некоторым другим, которые я забыл, обычно лучше использовать профессионально написанный инструмент резервного копирования, например barman или backrest. Эти инструменты сделают физическую копию файлов базы данных плюс связанные с ними WAL-файлы, необходимые для обеспечения согласованности базы данных. Помимо того, что это позволит избежать некоторых из уже упомянутых проблем, это позволит вам выполнять восстановление на нужный момент времени. Если вы используете pg_dump для сохранения содержимого базы данных раз в день - и предположим, что ваша база данных достаточно мала, чтобы такой подход был целесообразен, - то в случае катастрофы вам придется вернуться к последней ежедневной резервной копии, а все изменения с тех пор исчезнут. С другой стороны, если вы используете правильно настроенный инструмент резервного копирования, вы должны быть в состоянии организовать воспроизведение любого WAL, который был создан после последнего резервного копирования и успешно заархивирован или передан на другой сервер. А это значит, что вы потеряете всего несколько секунд данных или вообще не потеряете их, а не несколько часов. Для многих людей это очень важно.

Но все это не означает, что pg_dump не является инструментом резервного копирования. Это значит, что pg_dump не является подходящим инструментом резервного копирования для большинства людей. Использование хорошо поддерживаемого и, возможно, профессионально поддерживаемого инструмента имеет массу преимуществ и почти всегда будет лучше, чем самодельный скрипт. Независимо от того, использует ли ваш самодельный скрипт pg_basebackup, pg_dump или какой-то другой механизм. Но если в вашем конкретном случае то, что делает pg_dump, больше подходит для ваших нужд, то используйте его и не позволяйте никому заставлять вас чувствовать себя виноватым за это. Я делал это в течение долгого времени, и одна из вещей, которая мне нравилась (как относительному новичку в PostgreSQL) - это то, что у меня были все мои данные в по сути текстовых файлах. Если у меня была копия каталога данных на диске, то я должен был полагаться на PostgreSQL, чтобы разобраться с этим, и если он не мог этого сделать, то у меня были проблемы. Но я был уверен, что бы ни прозошло, я всегда смогу найти способ восстановить свои данные из вывода pg_dump, потому что текстовый файл - это то, что я могу прочитать, понять и извлечь из него данные тем или иным способом, даже если для этого придется использовать awk и sed.

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

Вторая, более серьезная проблема с утверждением «pg_dump не является инструментом резервного копирования» заключается в том, что оно недействительно. Не предлагая никаких конкретных фактов, теорий или аргументов, он утверждает, что если вы думаете, что pg_dump - это инструмент резервного копирования, то вы глупы. На самом деле, вы настолько глупы, что говорящему не нужно оправдываться, утверждая, что pg_dump не делает того, о чем в документации ясно сказано, что он делает это уже более двух десятилетий. Если вы еще не слышали, как кто-то другой сказал это, то позвольте мне быть первым: вы не глупы, если думаете, что pg_dump можно использовать для резервного копирования экземпляра PostgreSQL. Вполне можно. Часто это не самый лучший подход, но иногда он может быть просто идеальным. Упомянутый выше случай, когда вы хотите иметь содержимое вашей базы данных в текстовом формате, который можно прочитать с помощью инструментов, не связанных с PostgreSQL, - это лишь один пример того, когда это может быть. Существуют и другие.

В целом, вы не глупы, если хотите получить четкое и внятное обоснование любой передовой практики, которую кто-то советует вам соблюдать, будь она связана с PostgreSQL или же нет. Лучшие практики - это плод человеческого опыта. Люди пробуют множество вещей и выясняют, какие из них работают хорошо, а что идет не так, когда они делают что-то другое. Именно то, что идет не так, когда лучшая практика не соблюдается, делает ее лучшей практикой. Способность объяснить, в чем опасность, делает человека экспертом. «Не используйте pg_dump», как и любое другое правило, имеет ту же силу, что и аргументы оправдывающие pg_dump.