RE:NODE

Базы данных12 мин чтения

mongodump и mongorestore: резервные копии, которые восстанавливаются

Как правильно делать резервные копии MongoDB: параметры mongodump, архивы и gzip, почему дамп не является точкой во времени, восстановление одной коллекции и рабочее расписание.

0 прочтений

Коротко это две команды. mongodump --uri="$MONGODB_URI" --archive=shop-2026-09-21.gz --gzip записывает все коллекции в один сжатый файл, пока сервер продолжает работать. mongorestore --uri="$MONGODB_URI" --archive=shop-2026-09-21.gz --gzip --drop возвращает их на место. Обе - отдельные программы, не входящие в саму базу данных, обе принимают параметры подключения так же, как ваше приложение, и ни одна не останавливает сервер.

Длинная версия - та часть, которая решает, останутся ли у вас данные через год. mongodump - это логическая резервная копия: копия документов, считанная обычными запросами. Это делает её переносимой между версиями и машинами, но означает и то, что она не мгновенна. На отдельном сервере дамп читает коллекции одну за другой, пока записи продолжаются, поэтому архив согласован внутри каждой коллекции, но не между ними. Знать точно, что это гарантирует, а что нет, - основная часть этой статьи.

Что производит mongodump и где его взять#

Начиная с MongoDB 4.4 эти инструменты не входят в состав сервера. mongodump, mongorestore, mongoexport, mongoimport и bsondump поставляются как MongoDB Database Tools, отдельный пакет со своей нумерацией версий в серии 100.x. Установите их на ту машину, которая будет делать копии (сервер приложения, ноутбук, там, где работает ваш планировщик), и они будут обращаться к базе по тому же хосту и порту, что и ваше приложение.

По умолчанию mongodump записывает каталог:

code
dump/  shop/    orders.bson    orders.metadata.json    customers.bson    customers.metadata.json

Каждый файл .bson - это сырые документы в двоичном виде. Каждый .metadata.json хранит параметры коллекции и определения индексов, благодаря чему mongorestore знает, что после загрузки нужно перестроить индексы. Удалите файл метаданных, и вы восстановите данные без индексов, а обнаружить эту дорогую ошибку в продакшене неприятно.

--archive заменяет этот каталог одним потоком, чего вам почти всегда и нужно: один файл, который можно назвать, переместить, проверить контрольной суммой и скачать. --archive без имени файла пишет в стандартный вывод, поэтому дамп можно передать по конвейеру прямо в восстановление на другой машине, не касаясь диска ни на одной из них.

Создание дампа#

bash
$ mongodump --uri="mongodb://backup:pw@db.example.net:27017/?authSource=admin" \      --db=shop \      --archive="shop-$(date +%F).gz" --gzip

Параметры подключения берутся либо из --uri, либо из отдельных флагов (--host, --port, -u, -p, --authenticationDatabase), но не из обоих сразу. Пользователю нужна роль backup: это в точности набор привилегий, которого требует инструмент, и ничего лишнего. Если вы ещё выясняете, как должен выглядеть URI, в статье строки подключения MongoDB он разобран по частям.

ПараметрПо умолчаниюЧто делает
--db, --collectionвсеОграничивают то, что попадает в дамп
--archive=FILEвывод в каталогОдин файл вместо папки
--gzipвыкл.Сжатие; часто до четверти размера
--out=DIRdump/Куда идёт вывод в каталог
--query='{...}'нетДамп части данных; нужен --collection
--excludeCollectionнетПропустить коллекцию, можно повторять
--numParallelCollections4Сколько коллекций выгружается одновременно
--readPreferenceprimaryЧитать с вторичного узла
--oplogвыкл.Только для наборов реплик, см. ниже
--dumpDbUsersAndRolesвыкл.Включить пользователей, определённых в этой базе

Два из них стоит рассмотреть внимательнее. --query превращает дамп в экспорт части коллекции, так вы вытаскиваете данные одного клиента для запроса поддержки, не копируя 40 GB. А --numParallelCollections=4 стоит по умолчанию, потому что четыре воркера загружают большинство небольших серверов; на плане в 1 GB значение 1 делает дамп медленнее, а базе заметно легче, пока он идёт.

Пользователи и роли не включаются, пока вы не попросите. Они хранятся в admin.system.users и admin.system.roles, поэтому либо выгрузите заодно базу admin, либо используйте --dumpDbUsersAndRoles вместе с --db. Восстановление, которое проходит успешно, а потом отклоняет все входы, обычно объясняется именно этим.

Согласованность: то, в чём ошибаются все#

mongodump читает коллекции последовательно. Если он начинается в 02:00 и заканчивается в 02:06, то users.bson отражает 02:00, а orders.bson - 02:06. Заказ, записанный в 02:03 и ссылающийся на пользователя, созданного в 02:03, может попасть в архив с заказом, но без пользователя. Для большинства приложений это теоретическая проблема; для всего, где висящая ссылка ломает экран, - нет.

replica set onlyreplays the gapСтарт дампа02:00users.bsonпрочитан в 02:00orders.bsonпрочитан в 02:06oplog.bsonс 02:00 до 02:06Восстановление--oplogReplay
Почему --oplog делает дамп единой точкой во времени

Решение - --oplog, который дополнительно захватывает журнал операций за окно, которое охватывает дамп. Восстановление с --oplogReplay затем применяет эти операции поверх, приводя все коллекции к одному моменту: к моменту, когда дамп закончился. У него два требования, которые исключают его для многих. Ему нужен набор реплик, потому что у отдельного mongod журнала операций нет вообще, и он выгружает весь экземпляр, поэтому его нельзя сочетать с --db или --collection.

Значит, на одном отдельном сервере честных вариантов три: принять согласованность по коллекциям, чего для подавляющего большинства приложений достаточно; остановить записи на время дампа, что реалистично для небольшой базы, выгружающейся за двадцать секунд; или запустить экземпляр как набор реплик из одного члена, чтобы журнал операций появился. Одного делать нельзя: считать, что у вас есть восстановление на момент времени, потому что есть ночной дамп. Его нет, и выяснять это лучше не во время инцидента. Та же граница проходит и в реляционном мире: pg_dump и pg_restore проводит ту же черту между логическим дампом и настоящим восстановлением на момент времени.

Восстановление#

bash
$ mongorestore --uri="mongodb://root:pw@db.example.net:27017/?authSource=admin" \      --archive=shop-2026-09-21.gz --gzip --drop
ПараметрЧто делает
--dropУдаляет каждую коллекцию из дампа перед её восстановлением
--nsInclude, --nsExcludeВосстановить только соответствующие пространства имён или все, кроме них
--nsFrom, --nsToПереименовать базы или коллекции при восстановлении
--noIndexRestoreПропустить построение индексов, обычно плохая идея
--numParallelCollectionsСколько коллекций восстанавливается одновременно, по умолчанию 4
--numInsertionWorkersPerCollectionПо умолчанию 1; увеличьте для одной огромной коллекции
--stopOnErrorПрервать на первой ошибке, а не продолжать
--oplogReplayПрименить oplog.bson после данных, для дампов с --oplog
--preserveUUIDСохранить UUID коллекций; требует --drop
--writeConcernПонизьте при массовой загрузке

Нюанс --drop ловит всех хотя бы раз. Он удаляет коллекции, которые есть в дампе. Он не трогает коллекции, которые есть на целевом сервере, но отсутствуют в архиве, поэтому восстановление в неочищенную базу оставляет старые коллекции и выглядит так, будто всё получилось. Если нужен чистый результат, сначала удалите базу или восстанавливайте в свежую.

Перестроение индексов - обычно самая медленная часть восстановления, потому что каждый индекс строится с нуля после того, как документы загружены. Поэтому восстановленная база нередко работает быстрее той, из которой она пришла: индексы получаются свежими, а не фрагментированными. Не хватайтесь за --noIndexRestore ради скорости, если только вы не собираетесь тут же построить индексы сами: до этого приложение будет непригодно. Что именно делают эти построения, описано в статье индексы и схема данных MongoDB.

Прежде чем восстанавливать что-то, в чём вы не уверены, загляните внутрь. bsondump --quiet dump/shop/orders.bson | head -n 3 выводит первые документы как JSON, а архив можно восстановить в черновую базу и посчитать:

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsFrom='shop.*' --nsTo='shop_check.*'$ mongosh --quiet --eval 'db.getSiblingDB("shop_check").orders.countDocuments()'

Восстановление одной коллекции или под другим именем#

Типичная авария - это не «сервер пропал». Это «кто-то в 11:40 выполнил удаление без фильтра в одной коллекции». Вам нужна эта коллекция обратно, со вчерашнего вечера, а всё остальное нетронутым.

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsInclude='shop.orders' --drop

--nsInclude принимает шаблоны, так что --nsInclude='shop.*' восстанавливает одну базу из архива всего экземпляра. Более безопасная версия той же операции восстанавливает рядом с живыми данными, а не поверх них, чтобы можно было сравнить, прежде чем принять решение:

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsInclude='shop.orders' \      --nsFrom='shop.orders' --nsTo='rescue.orders'

Теперь в rescue.orders лежит вчерашняя копия. Сосчитайте её, выборочно проверьте несколько документов, определите, каких не хватает в живой коллекции, и скопируйте только их с помощью агрегации и $merge. Это медленнее, чем --drop, но не выбрасывает записи, сделанные между копией и ошибкой, а это обычно именно то, что вам нужно.

--nsFrom и --nsTo - также способ создать staging-копию: восстановите архив продакшена в базу shop_staging на другом сервере и направьте на неё staging. Делайте это на другом сервере, а не на продакшене, если только вам не нравится обнаруживать, что восстановление заполнило диск.

mongoexport и mongoimport - это не резервные копии#

mongoexport пишет JSON или CSV. Он действительно полезен, чтобы передать данные тому, у кого есть таблица, или загрузить тестовые данные. Резервной копией он не является по одной конкретной причине: по умолчанию он пишет relaxed extended JSON, который не сохраняет типы BSON при обратном преобразовании. 64-битное целое может вернуться как double, Decimal128 теряет точность, а даты и идентификаторы объектов становятся неоднозначными. --jsonFormat=canonical сохраняет типы, но вывод всё равно больше, медленнее и без определений ваших индексов.

Правило простое. mongodump и mongorestore - для резервных копий и переноса между экземплярами MongoDB, потому что они точно переносят типы BSON и метаданные. mongoexport и mongoimport - для обмена со всем, что не MongoDB.

Другие виды резервных копий и их компромиссы#

Снимки файловой системы или тома. Быстро и для всего экземпляра, но действительны только если снимок атомарен по всем томам, где лежат данные и журнал. Два тома, снятые с разницей в секунду, дают базу, которая может не запуститься. Там, где атомарность не гарантирована, db.fsyncLock() сбрасывает данные и блокирует записи на время, а это реальная остановка, как бы коротка она ни была.

Копирование каталога данных работающего сервера. Это не резервная копия. Файлы пишутся, пока вы их копируете, и в результате получается повреждённая база, которая выглядит нормально, пока не окажется вашей единственной копией.

Слоты резервных копий вашего хостинга. Они защищают сервер целиком, запускаются за секунды и подходят для случая «сервер сломался». На RE:NODE каждый тариф баз данных включает слоты резервных копий: они создаются по запросу или по расписанию, хранятся вне защищаемой машины, восстанавливаются кнопкой, доступны для скачивания и блокируются, чтобы ротация не могла удалить ту копию, на которую вы рассчитываете. Честное ограничение записано мелким шрифтом на каждой платформе: удаление сервера удаляет его резервные копии, в том числе заблокированные. Поэтому храните архив mongodump ещё и скачанным в другом месте. Два механизма, которые ломаются по-разному, - в этом весь смысл; тот же довод развёрнуто изложен в статье резервные копии, которые действительно восстанавливаются.

Расписание, хранение и запас места на диске#

Порядок, который работает, и он один и тот же для любой базы данных:

  1. Делайте дамп каждую ночь в самый тихий час, с датой в имени файла, со сжатием.
  2. Уносите архив с машины, на которой он создан. Дамп на том же диске защищает от неудачного запроса и больше ни от чего.
  3. Храните семь ежедневных и четыре еженедельных копии и удаляйте лишнее автоматически. Ручная чистка кончается заполненным диском, а сервер базы данных с полным диском перестаёт принимать записи.
  4. Раз в квартал восстанавливайте самый свежий архив в черновую базу, считайте документы в важных вам коллекциях, направьте на неё копию приложения и удаляйте.

Четвёртый шаг пропускают все, и только он превращает файл в резервную копию. Статьи проверка восстановления до того, как оно понадобится и резервные копии базы данных и доказательство того, что они восстанавливаются существуют из-за того, как часто пропускают четвёртый шаг.

Вкладка Schedules в панели принимает cron-выражение и запускает упорядоченные задачи с паузами между ними (резервную копию, действие с питанием), так что ночная копия на стороне платформы - это настройка, а не скрипт, который нужно поддерживать в живых. Часть с mongodump принадлежит тому месту, где работает ваше приложение или планировщик, направленная на хост и порт базы. О том, где находятся эти элементы управления, рассказывают руководства по панели.

Следите за диском. Дампу, записанному на собственное хранилище сервера базы данных, нужно место под сжатый архив сверх данных и индексов, а на плане в 20 GB при 12 GB занятых его может не оказаться. Пишите архив в другое место или передавайте потоком: mongodump --archive --gzip | ssh backup-host 'cat > shop.gz' вообще не кладёт файл на сервер базы данных.

Ошибки, которые вы действительно увидите#

`Failed: error connecting to db server` - проблема подключения, а не резервного копирования. Неверные хост или порт, сервер привязан только к loopback-адресу или брандмауэр. Сначала попробуйте тот же URI в mongosh.

`Failed: ... Authentication failed` - обычно не хватает --authenticationDatabase admin, это тот же вопрос authSource, что задают и драйверы.

`E11000 duplicate key error collection` - восстановление в коллекцию, где эти документы уже есть. Вам нужен был --drop или свежая база.

`Failed: restore error: ... oplog.bson: no such file` - --oplogReplay на дампе, снятом без --oplog. Журнал операций есть, только если вы попросили его во время дампа.

`Failed: cannot use --oplog with --db or --collection` - --oplog работает только для всего экземпляра целиком.

Восстановление, завершившееся без индексов - файлы метаданных потеряны или задан --noIndexRestore. Перестройте индексы по определениям вашей схемы.

Восстановление, которому не хватило памяти или диска - построение индексов и параллельная вставка расходуют память. Уменьшите --numParallelCollections и убедитесь, что на целевом сервере есть место под данные плюс индексы, а это больше, чем подсказывает размер сжатого архива.

FAQ#

Блокирует ли mongodump базу данных?

Нет. Он читает обычным путём запросов, поэтому сервер продолжает работать. Он всё же конкурирует за CPU, память и пропускную способность диска, а на небольшом экземпляре это заметно, поэтому запускайте его, когда приложение не загружено, и подумайте о снижении --numParallelCollections.

Является ли mongodump копией на момент времени?

Только с --oplog на наборе реплик и при восстановлении с --oplogReplay. Без этого каждая коллекция согласована внутри себя, но коллекции читаются в слегка разное время. Для большинства приложений это приемлемо; решайте сознательно, а не по умолчанию.

Можно ли восстановить дамп в более новую версию MongoDB?

Обычно да: документы BSON переносимы, и это стандартный способ перехода между версиями. Старые дампы, восстанавливаемые на гораздо более новые серверы, иногда упираются в параметры индексов, которые с тех пор изменились; --convertLegacyIndexes существует именно для такого случая. Восстановление в более старую основную версию, чем та, из которой пришёл дамп, - не то, на что стоит полагаться.

Как восстановить только одну коллекцию?

mongorestore --archive=file.gz --gzip --nsInclude='db.collection'. Если в живой коллекции ещё есть данные, которые вы хотите сохранить, восстанавливайте под другим именем с --nsFrom и --nsTo и сливайте, а не удаляйте живую.

mongodump или кнопка резервной копии на хостинге?

Обе, потому что они ломаются по-разному. Копия платформы быстро восстанавливает весь сервер и исчезает вместе с ним. Скачанный архив mongodump переносится на любой хостинг и любую поддерживаемую версию. Ни то, ни другое само по себе не является стратегией резервного копирования.

Сколько времени занимает восстановление?

Загрузка документов идёт примерно так быстро, как позволяют диск и память; перестроение индексов обычно занимает дольше. Несколько гигабайт на NVMe - это минуты. Если вам нужно число, которое можно кому-то пообещать, измерьте его на своих данных во время учебного восстановления, потому что только эта цифра что-то значит.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000