Вопросы и ответы

Как проверить перенос данных на новый сервер без ошибок: чек-лист из 5 шагов

Проверка переноса данных на новый сервер — это пять последовательных шагов: сверка контрольных сумм и объёмов файлов, валидация целостности баз данных и межтабличных связей, тест прав доступа и…

Почему важно проводить валидацию после миграции

После физического копирования байтов между серверами лежит скрытый пласт проверок. Утилиты вроде `rsync` или `robocopy` могут отчитаться об успешном завершении, но не умеют различать частично повреждённый сектор на диске-источнике, нарушенную транзакцию в PostgreSQL, несовпадающий collation в MySQL или устаревший токен для сервисного аккаунта. По данным отчёта Enterprise Strategy Group за 2025 год, у 62% компаний миграция между серверами сопровождалась хотя бы одним скрытым дефектом: от расхождения количества строк в таблицах до потери индексов, а полное восстановление занимало в среднем 11 часов.

Именно поэтому валидация после переноса — обязательный этап, а не опциональный. К ней предъявляют три требования:

1. Воспроизводимость. Результат проверки одного и того же состояния должен совпадать независимо от администратора. Добиться этого можно фиксированными командами (`sha256sum`, `pg_dump --schema-only`, `robocopy /MIR`) и эталонными отчётами.

Полезная подборка по близкой теме — главная подборка.

2. Сопоставимость источника и приёмника. Все сравнения выполняются между исходным и целевым сервером, а не «внутри нового сервера». Только так можно доказать, что данные не изменились в пути.

3. Документирование. Каждое действие оформляется отдельным артефактом: файл с контрольными суммами, лог проверки, скриншот результата SQL-запроса. Без артефактов валидация считается незавершённой.

Хорошая практика — отделять валидацию от самой миграции и проводить её на отдельной учётной записи с правами read-only на источник и read-write на приёмник. Это исключает случайную перезапись на источнике и даёт независимый аудитный след.

Смежные инструкции собраны здесь — цифровые сервисы.

При планировании опираются на два показателя из непрерывности бизнеса:

  • RPO (Recovery Point Objective) — допустимая потеря данных по времени. При RPO = 15 минут любая проверка должна уложиться в этот интервал, включая откат в случае несовпадения.
  • RTO (Recovery Time Objective) — допустимое время простоя. Для production-систем редко превышает 1–4 часа, поэтому валидация занимает не больше 30% от RTO.

Если шаги валидации не укладываются в RPO/RTO, перенос разбивают на этапы или выносят в окно обслуживания с предварительным уведомлением пользователей.

Этап 1: Сверка контрольных сумм и объёма файлов

Первый шаг проверяет, что на уровне файловой системы приёмник получил ровно те же байты, что и источник. Для серверов на Linux применяют связку `find` + `sha256sum` + `diff`; для Windows — `Get-FileHash` + `Compare-Object` в PowerShell. SHA-256 предпочтительнее MD5: коллизии в MD5 к 2026 году легко генерируются за минуты на обычной рабочей станции.

Типичная последовательность на источнике:

cd /var/data
find. -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/source.sha256

На приёмнике:

cd /var/data
find. -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/target.sha256
scp source:/tmp/source.sha256 /tmp/
diff -q /tmp/source.sha256 /tmp/target.sha256

Если `diff` возвращает ненулевой код — списки файлов различаются. Дополнительно сверяют количество строк `wc -l` и совокупный размер `du -sb`. Расхождение больше 0,01% по объёму — повод прервать валидацию и повторить миграцию, не дожидаясь остальных шагов.

Под Windows аналогичная проверка идёт через PowerShell:

Get-ChildItem -Recurse | Get-FileHash -Algorithm SHA256 | Export-Csv hashes.csv
Compare-Object (Get-Content src.csv) (Get-Content dst.csv)

Для больших объёмов (десятки терабайт) используют `rsync -avh --checksum --dry-run` — он сообщает только о файлах, у которых изменился размер или контрольная сумма, без реального копирования. Это ускоряет повторную проверку до десятков минут вместо часов.

Дополнительно сверяют временные метки: `stat -c '%Y %n'` на Linux или `Get-ItemProperty LastWriteTime` на Windows. Расхождение больше 1 секунды на уровне файла сигнализирует о неполной синхронизации или вмешательстве.

Этап 2: Проверка целостности баз данных и связей

После сверки файлов переходят к структурированным данным. Здесь сравнивают количество строк, контрольные суммы таблиц, состояние индексов, внешних ключей и ограничений (`CHECK`, `UNIQUE`, `NOT NULL`). Работа идёт на уровне СУБД, потому что часть данных может быть закодирована и не поддаваться побайтовой проверке.

Для PostgreSQL применяют встроенную функцию `pg_checksums` (включается для кластера) или считают хэши через `hashtext()` и `md5()`:

SELECT count(*) FROM orders;
SELECT md5(string_agg(id::text, ',' ORDER BY id)) FROM orders;

Эти же запросы выполняют на источнике и приёмнике под одной и той же ролью. Совпадение количества строк и агрегированного хэша даёт 99% гарантии целостности таблицы. Для таблиц больше 100 млн строк добавляют разбивку по партициям или диапазонам дат, чтобы избежать долгого агрегирования.

MySQL предлагает утилиту `mysqlcheck` с флагом `--check --use-frm`: она проверяет целостность таблиц по внутренним контрольным суммам движка InnoDB. На приёмнике запускают:

mysqlcheck -u root -p --check --all-databases

Дополнительно сравнивают метаданные: `information_schema.TABLES` (DATA_LENGTH, INDEX_LENGTH, AUTO_INCREMENT) и `information_schema.STATISTICS` для индексов. Расхождение AUTO_INCREMENT чаще всего вызвано незавершённой репликацией.

MongoDB проверяют через `db.collection.validate({full: true})` на ключевых коллекциях, а также через `db.collection.stats()` — размер, количество документов, размер индексов.

После успешной проверки таблиц переходят к межтабличным связям. Здесь возможны три дефекта:

1. Ссылочная целостность нарушена — внешний ключ `orders.user_id → users.id` ссылается на несуществующего пользователя. На production это невозможно (MySQL и PostgreSQL запрещают), но на staging БД с отключёнными FK может пройти. Проверяют SQL-скриптом:

SELECT o.id FROM orders o LEFT JOIN users u ON u.id = o.user_id WHERE u.id IS NULL;

2. Дубликаты в уникальных индексах — перенесённые данные из двух систем сошлись в одну. Обнаруживается через `SELECT field, count() FROM table GROUP BY field HAVING count() > 1`.

3. Сломанные триггеры и представления — DDL-объекты могли не попасть в дамп. Сверяют системные каталоги: `pg_trigger`, `mysql.proc`, `information_schema.VIEWS`.

Все запросы и их результаты сохраняют в отдельный каталог `validation/db/`, а итог фиксируют в сводной таблице: таблица, источник строк, приёмник строк, источник хэша, приёмник хэша, расхождение, статус.

Этап 3: Тестирование прав доступа и конфигураций безопасности

Файлы и базы данных перенесены, но под старыми ACL, владельцами и сервисными учётками. Без проверки безопасности сервис либо не запустится (нет доступа на чтение), либо даст избыточные права (файлы конфигурации доступны группе `world`).

На Linux проверяют владельцев и права:

find /etc/app /var/app -not -user appuser -o -not -group appgroup
find /etc/app -perm -o+r # мировое чтение на чувствительные файлы

Чувствительными считаются файлы с приватными ключами (`.pem`, `.key`), конфиги с паролями и сертификаты. Допустимый режим — `640` или `600`, владелец — сервисный пользователь.

На Windows сравнение через `icacls`:

icacls C:\App\* /save acl.txt /t
icacls \\source\App\* /save src_acl.txt /t
fc /b acl.txt src_acl.txt

Расхождения в ACE-записях, особенно в строках `BUILTIN\Administrators` или `CREATOR OWNER`, разбирают вручную.

Дальше проверяют конфигурации сервисов: `nginx`, `Apache`, `systemd-unit`, `Windows Service`. Сравнивают:

  • путь к исполняемому файлу;
  • переменные окружения (`EnvironmentFile`, `Environment=`);
  • учётную запись запуска (`User=`, `logon_as`);
  • сетевые порты и привязки;
  • открытые файрволом правила (`iptables -L -n -v`, `netsh advfirewall firewall show rule`).

Отдельно сверяют TLS-сертификаты. Частая ошибка — после миграции сертификаты остались на старом сервере, а новый использует самоподписанные. Проверяют через `openssl x509 -in cert.pem -noout -subject -dates -issuer` на источнике и приёмнике. Дата `notAfter` должна быть актуальной и совпадать между узлами.

Для сервисных аккаунтов (PostgreSQL → `pg_hba.conf`, приложение → API-ключ) проверяют:

  • актуальность токена;
  • наличие прав на новом сервере;
  • совпадение `secrets-manager`-ссылок, если используется Vault, AWS Secrets Manager или Azure Key Vault.

Без положительного результата этого шага переходить к функциональному тестированию нельзя: даже идеальные данные будут недоступны приложению.

Этап 4: Функциональное тестирование критических сервисов

Последний содержательный шаг проверяет, что мигрированные данные работают в реальных сценариях. Здесь применяют подход «снизу вверх»: сначала тестируют отдельные компоненты, затем интеграцию, затем end-to-end.

Начинают с проверки сетевой связности. С нового сервера вызывают:

ping -c 5 source.internal
traceroute db.internal
nc -zv api.internal 443
ss -tnp state established

Пинг должен укладываться в 50 мс внутри одного ЦОД и в 150 мс между регионами. Потеря пакетов — не больше 0,01%. Если тайм-ауты или `Connection refused` — возвращаются к Этапу 3 и проверяют правила firewall и маршрутизацию.

Дальше тестируют сервисы уровня приложения. Для веб-сервиса:

curl -fsS https://service.local/healthz
curl -fsS -H "Authorization: Bearer $TOKEN" https://service.local/api/v1/orders

Возвращённые коды должны быть `200 OK`. Код `503 Service Unavailable` сигнализирует о неполной инициализации (например, не подтянулся конфиг). Проверяют логи приложения: `journalctl -u service-name --since "5 min ago"` на systemd-серверах, Event Viewer на Windows.

Затем запускают интеграционные тесты, которые уже есть в проекте. Если таких тестов нет, составляют минимальный набор:

КатегорияПример проверкиДопустимый результат
ЧтениеGET /api/v1/customers/{id}200, поля совпадают с источником
ЗаписьPOST /api/v1/orders201, запись появляется в БД приёмника
АвторизацияЗапрос с истёкшим токеном401, без побочных эффектов
ОчередьПубликация задачи в RabbitMQ/KafkaСообщение доставлено и обработано
ПоискЗапрос в Elasticsearch/OpenSearch200, top-10 выдачи совпадают

Все запросы подают как с production-токеном, так и с тестовым. Расхождение ответов между источником и приёмником — повод остановить миграцию и вернуться к Этапу 2.

Отдельно проверяют метрики производительности. Сравнение идёт на одинаковом железе, одинаковой нагрузке, одинаковом объёме данных. Допустимое отклонение по latency p95 — не больше 15% от источника. Если запросы на приёмнике выполняются на 30% дольше — высока вероятность, что индексы были созданы в неправильном порядке, не подключена оптимизация `work_mem`, либо СУБД не прогрела кэш.

После успешного функционального теста переключают DNS или балансировщик на новый сервер. Делают это в режиме `canary`: 5% трафика в течение 30 минут, 25% в течение часа, 100% — после подтверждения метрик.

#ПроверкаМетодКритерий «готово»Кто отвечает
1Контрольные суммы файлов совпадают`sha256sum` + `diff`0 расхожденийDevOps
2Объём перенесённых данных`du -sb` или `Get-ChildItem \Measure-Object`Δ ≤ 0,01%DevOps
3Количество строк в таблицах`SELECT count(*)`Δ = 0DBA
4Хэш агрегата таблицы`md5(string_agg(...))`строки источника = приёмникаDBA
5Ссылочная целостность FK`LEFT JOIN... WHERE NULL`0 «висящих» строкDBA
6Владельцы и права на файлах`stat`, `icacls`только разрешённые owner/groupSecurity
7Режимы приватных файлов`find... -perm -600`0 файлов с `o+r`Security
8TLS-сертификаты валидны`openssl x509 -checkend 2592000`> 30 дней до истеченияSecurity
9Сервисные учётки работаютпроверка токенов, ACL0 ошибок `401/403`DevOps
10Сетевая связность`ping`, `nc -zv`0 потерь, latency p95 ≤ 150 мсNetwork
11Endpoint /healthz отвечает`curl -fsS`200 OKDevOps
12Интеграционные тесты зелёныеCI-пайплайн100% passQA
13Latency p95 запросовнагрузочный тест k6/wrkΔ ≤ 15% к источникуQA
14Бэкап приёмника настроенVeeam/Bacula/rsnapshotрасписание активноBackup-admin
15Мониторинг подключёнZabbix/Prometheusметрики поступают ≥ 5 минSRE
16Журнал аудита ведётсяsyslog/journal forwardingсобытия пишутсяSecurity
17План отката готовrunbook + снапшотRTO ≤ 30 минDevOps
18Уведомление пользователейписьмо/статус-страницаотправлено за 24 чService Owner

Когда валидация показывает расхождения и что делать

Несовпадения выявляются на любом из этапов. К этому нужно быть готовым заранее: без плана отката миграция превращается в инцидент. Опираются на сценарии, которые встречаются чаще всего.

Сценарий 1: расходятся контрольные суммы. Останавливают синхронизацию, фиксируют список отличающихся файлов и сравнивают по дате. Причины: прерванная передача, повреждение диска, вмешательство антивируса на Windows. Решение — повторный `rsync` только по проблемным файлам (`rsync --files-from=missing.txt`), затем повтор шага 1.

Сценарий 2: количество строк в таблице меньше. Причина — незавершённая транзакция в источнике на момент снимка или нарушение порядка применения WAL. Решение — восстановить БД из последнего проверенного бэкапа, повторить инкрементальную репликацию, повторно валидировать шаг 2.

Сценарий 3: внешние ключи нарушены. Это признак того, что в staging-режиме были отключены FK, либо часть таблиц перенесли позже остальных. Решение — выполнить перенос таблиц в порядке родитель → потомок, включить FK перед финальной сверкой.

Сценарий 4: права доступа не совпадают. Причины — разные ACL-схемы между серверами, миграция через root без сохранения `xattr` на Linux или `Owner` на Windows. Решение — повторное копирование с сохранением атрибутов: `rsync -aX` на Linux, `robocopy /COPYALL` на Windows. После повтора перепроверить шаг 3.

Сценарий 5: TLS-сертификаты просрочены или отсутствуют. Причина — на источнике были wildcard-сертификаты от внутреннего CA, не скопированные автоматически. Решение — выпустить новый сертификат на новом сервере или скопировать PKI-цепочку из защищённого хранилища.

Сценарий 6: интеграционные тесты красные. Здесь два направления: либо источник отдаёт «правильные» ответы за счёт старых костылей, либо приёмник работает «правильнее», и тесты устарели. Решение — сравнить трассировку запроса, понять, какая часть отличается, и сознательно выбрать, какую систему выровнять под какую.

Сценарий 7: нагрузочный тест просаживается на 30–50%. Причины: не активирован `huge pages`, отличается параметр `max_connections`, нет прогрева буферного пула. Решение — выполнить `pg_prewarm` или эквивалент, проверить конфигурацию СУБД, повторить прогон после прогрева.

Сценарий 8: раздел про логи и аудит не наполняется. Причина — journal/syslog не перенаправлен на центральный коллектор. Решение — настроить `rsyslog`/`fluent-bit`/`Promtail`, повторить запуск сервиса, дождаться поступления событий в SIEM (Splunk, ELK, MaxPatrol SIEM).

Любое расхождение фиксируется в журнале инцидентов с указанием причины, времени обнаружения, ответственного и корректирующих действий. Без такой записи валидация не считается закрытой.

Проверка первоисточников

Где сверить правила и документы

Ссылки помогают быстро перейти от советов в статье к официальным реестрам, правилам или справочным сервисам. Перед оплатой или претензией сохраняйте дату проверки.