Прерванная миграция не всегда просто «остановилась на полпути». Она могла завершиться до сохранения одной единицы данных, после подтверждения некоторых изменений или в ситуации, когда целевая система ответила неоднозначно. Процесс также мог завершиться, но оставить расхождения. Чтобы решить, как продолжить работу, команда должна восстановить ход событий на основе проверяемых свидетельств, а не полагаться только на код завершения или последний зарегистрированный идентификатор.
Практический вопрос состоит не только в том, как возобновить неудачную миграцию данных в PHP, но и в том, что можно утверждать о состоянии каждой единицы данных и какие проверки необходимы перед повтором операции. Такое различие снижает риск появления дубликатов, нарушения связей и ручных исправлений, которые сложно аудировать.
Сначала отличите остановившийся запуск от миграции с расхождениями

Остановившийся запуск — это запуск, в котором процесс перестал продвигаться, например из-за исключения, потери соединения или вмешательства оператора. Миграция с расхождениями, напротив, — это миграция, результат которой не соответствует ожидаемым условиям, хотя процесс завершился без ошибок. В ней могут быть пропущенные строки, неправильно преобразованные ключи или неполные связи.
Поэтому общего статуса вроде завершена или не удалась недостаточно. Стоит различать как минимум следующие состояния: выполняется, остановлена, завершена и завершена с расхождениями. Общий статус отражает ход работы, но не заменяет записи по каждой единице данных или проверку результата.
Прежде чем повторно запускать команду, сохраните доступные журналы и определите, какая система на этом этапе является источником истины. Если после миграции выполнялись записи, вносились ручные изменения или работали параллельные процессы, выясните, как они влияют на сравнение. Продолжение без этой информации может превратить расхождение, которое можно было расследовать, в потерю отслеживаемости.
Определите единицы работы и проверяемые контрольные точки
Выберите единицу работы, подходящую для данных и восстановления: это может быть сущность, группа связанных записей или стабильный раздел данных. Не используйте в качестве контрольной точки просто «последний обработанный ID». Такой ID доказывает в лучшем случае, что программа дошла до определённой позиции; он не подтверждает, что все предыдущие записи были корректно сохранены и что данные в целевой системе согласованы.
Для каждой единицы сохраняйте стабильный ключ источника, версию или идентификатор запуска, состояние и проверяемый результат. Контрольную точку нужно сопоставлять с целевой системой, например с помощью ключа целевой записи, контрольной суммы по значимым полям или проверочного запроса. Если данные могут меняться во время процесса, также зафиксируйте критерий выборки или применённый момент отсечения.
Решение зависит от среды. Если источник и целевая система используют одну транзакцию, она может служить свидетельством совместного подтверждения; если это разные системы, не предполагайте атомарность между ними. При интеграции через API потерянный ответ может оставить неясным, применил ли сервер операцию. Стратегия должна учитывать эту неопределённость и предусматривать последующую проверку, а не автоматически помечать единицу как неудачную или подтверждённую.
Фиксируйте по каждой единице, что было предпринято и подтверждено
Полезная для поддержки запись позволяет выяснить, кто запустил миграцию, какую единицу обрабатывал, когда изменилось её состояние и какие свидетельства это подтверждают. Различайте обработано — код выполнил определённые шаги — и подтверждено — есть надёжный сигнал, что ожидаемый результат существует в целевой системе. Добавляйте номер попытки, категорию ошибки и идентификатор корреляции, связывающий события процесса с внешними вызовами.
Состояния должны описывать рабочую ситуацию, а не только этап алгоритма. Например: ожидает обработки, выполняется, подтверждение неясно, подтверждено и требует проверки. Если процесс завершился аварийно, когда единица имела статус «выполняется», после перезапуска её следует считать неопределённой, пока целевая система не будет проверена. Не помечайте её как неудачную, не выяснив, успели ли возникнуть побочные эффекты.
Записывайте достаточно информации для расследования, но не помещайте в журналы учётные данные, секреты или ненужные персональные данные. По ошибкам должно быть возможно определить единицу и операцию, но отслеживаемость не должна расширять область раскрытия данных. Также определите, кто может просматривать и хранить эти записи.
Сравните инварианты, прежде чем решать, как продолжить
Инварианты — это условия, которые должны соблюдаться независимо от реализации миграции. Подсчёт записей по типам или разделам помогает найти различия, но этого недостаточно: два набора могут быть одинакового размера, но содержать разные записи. Сравнивайте бизнес-ключи, наличие записей, связи и значимые правила, например допустимые состояния или пересчитанные суммы.
Выбирайте проверки с учётом масштаба и объёма данных. Выборочная проверка может помочь диагностике, но сама по себе не доказывает корректность всего набора. Для полной проверки сравнивайте ключи или контрольные суммы по блокам и фиксируйте, какие блоки были проверены. Если преобразование намеренно меняет поля, задокументируйте, какие различия ожидаемы, а какие указывают на ошибку.
Если источник продолжает получать изменения, отделяйте расхождения, вызванные параллельными изменениями, от расхождений, вызванных миграцией. Может потребоваться зафиксировать окно отсечения, захватывать последующие изменения или повторить этап синхронизации. Без чёткого правила обработки параллельных изменений сравнение систем может давать ложноположительные результаты или пропускать новые данные.
Возобновляйте миграцию только при наличии свидетельств и учитывайте неопределённые результаты
Безопасное возобновление загружает список ожидающих обработки и подтверждённых единиц, но не считает действительными единицы с неопределённым статусом. Для последних проверьте целевую систему по стабильному ключу и сравните результат с ожидаемым результатом преобразования. Если данные совпадают, зафиксируйте подтверждение, не повторяя операцию; если записи нет, может быть уместно выполнить повторную попытку. Если запись существует, но её содержимое отличается, остановите обработку этой единицы и проведите расследование.
Если повтор операции может создать дубликаты или внешние эффекты — например, отправить уведомление, — используйте идемпотентную операцию или ключ идемпотентности, если соответствующая система это поддерживает. Если это невозможно, предусмотрите предварительную проверку и процедуру сверки. Не предполагайте, что исключение означает, что данные не были записаны: сбой мог произойти после подтверждения изменения, но до получения ответа.
Перед возобновлением убедитесь, что используются те же правила маппинга и работы с ключами, а также правильная версия кода или конфигурации. Контрольная точка, созданная с использованием другого преобразования, может вводить в заблуждение. В PHP команда миграции должна принимать идентификатор запуска и выдавать структурированные статусы; тогда специалист сможет сопоставить журнал с данными, а не полагаться на общие сообщения в консоли.
Установите условия остановки и завершите работу отчётом

Остановите продолжение при конфликтах ключей, недопустимых данных, для которых требуется бизнес-правило, осиротевших связях, непроверяемых неопределённых результатах или расхождениях, превышающих допустимые пределы. Остановитесь также, если имеющихся свидетельств недостаточно, чтобы установить, что произошло. В таких случаях передача вопроса на более высокий уровень и сохранение текущего состояния обычно безопаснее слепого повтора.
По завершении выполните общие проверки: сравните число подтверждённых единиц с ожидаемым, проверьте количество и ключи записей, связи и бизнес-правила, заданные для миграции. Подготовьте отчёт с указанием того, что было перенесено, проверено и обработано повторно, а также того, какие расхождения остаются нерешёнными; добавьте ссылки, по которым их можно расследовать. Не объявляйте работу завершённой только потому, что процесс завершился с нулевым кодом.
Критерий возобновления легко сформулировать, хотя для его соблюдения нужна техническая дисциплина: для каждой единицы нужно подтвердить выполнение, проверить, что операция не применялась, или отложить её для проверки. Такое явное состояние вместе с сопоставимыми инвариантами и полезными журналами позволяет продолжить миграцию PHP, не путая продвижение с успехом, а неопределённость — с разрешением на повтор операции.



