Инженерная практика с агентом · · 15 мин чтения

Миграция базы с агентом: сохранность данных и репетиция восстановления

Инварианты, конкурентная запись, продолжаемый перенос, проверка целостности и подтверждённое восстановление до live-изменений.

ИллюстрацияСгенерированная иллюстрация к материалу. Она передаёт идею статьи и не является экраном приложения.

Агент может написать правдоподобную миграцию и не объяснить главное: как переход переживут существующие данные и разные версии приложения. Успех schema command не устанавливает, что старый клиент продолжает записывать правильно, перенос сохранил смысл, а backup восстанавливается. Рассматривайте миграцию как изменение живого контракта. Source diff важен, но приёмка описывает записи, действующих читателей и писателей, а также восстановление при невозможности завершить следующий этап. Для удалённого ревью это особенно существенно: небольшая команда на экране телефона может иметь большой постоянный эффект, который не обращается простым закрытием запроса или остановкой текущего turn агента.

В упражнении вымышленный order service переименовывает delivery_note в delivery_instructions без изменения пользовательского текста. Пример намеренно небольшой. Это не готовая команда для production и не описание новой функции администрирования БД в GrantTap. Приложение помогает наблюдать Task, запросы, Files и доступные результаты. Сам rehearsal выполняют инструменты базы и release process. Полезный итог — конкретный пакет, который можно оценить до изменения настоящих данных. Описанные сценарии остаются планом проверки, пока не выполнены в вашем окружении; их наличие в статье не доказывает восстановление вашей базы, измеренную длительность операции или совместимость любого прежнего клиента с новой схемой.

Сначала инвариант, затем SQL

Запишите сохраняемые свойства. В примере каждый заказ сохраняет identity и точный delivery text; поддержанные версии читают и пишут в переходный период; посторонние записи не меняются. Это сильнее наличия нового column. Определите смысл пробелов, пустоты и missing. Если приложение различает их, rename не должен незаметно trim или normalize. Агенту нужен semantic target до выбора schema operations. Полезно также назвать область: все существующие заказы либо определённый набор, для которого есть обоснование. Неопределённая формулировка «перенести данные» не позволяет проверить полноту и провоцирует случайные фильтры, которые выглядят разумно автору скрипта, но исключают часть нужных записей.

Назовите non-goals. Мы не переделываем историю заказов, не переписываем инструкции моделью и не вводим другой length limit. Каждая такая перемена требует самостоятельной приёмки. Узкий rename делает verification понятной. Сохраните invariant в Task, чтобы следующая execution не приняла «продолжай» за разрешение широкой очистки соседних данных. Если во время чтения обнаружена полезная, но независимая проблема, запишите отдельную задачу. Не добавляйте исправление автоматически в data transformation: даже хорошая нормализация меняет объём доказательств, требования к обратимости и смысл сравнения, по которому команда планировала принять первоначальное ограниченное изменение persistent representation.

Оригинальная сгенерированная иллюстрация практикума. Это не экран продукта и не измеренный результат.
ИллюстрацияОригинальная сгенерированная иллюстрация практикума. Это не экран продукта и не измеренный результат.

Найдите настоящих читателей и писателей

Установите версии application, background jobs, importers и admin tools, использующих старое поле. Repository search — начало, не доказательство полного inventory. Важно, кто ещё пишет во время перехода. Старый mobile client и delayed worker живут дольше server release. Запишите ownership и update constraints. Unknown consumer остаётся пробелом, не исчезает от отсутствия reference в свежем source. Если ресурс используют вручную через консоль, это тоже часть реального контракта. Необъявленное изменение способно сломать операционную работу, даже когда все известные модульные тесты сервиса проходят и generated client успешно собирается с новой схемой.

Составьте compatibility plan для нужных сочетаний: old application с expanded schema, new application с ней же и contracted schema с оставшимися consumers. Агент называет проверяемые combinations и требующие operational confirmation. Graph и Health помогают навигации по сообщённым отношениям, но отсутствующая связь не доказывает отсутствие external writer. Проверьте contract и deployment inventory до решения об удалении. Если одну версию невозможно обновить быстро, это влияет на порядок миграции. Нельзя компенсировать неизвестный жизненный цикл клиента оптимистичной датой завершения перехода, выбранной потому, что она удобно помещается в план текущего спринта или кажется достаточной для всех пользователей.

Уточните engine и migration tool

Зафиксируйте database engine, существенную version и tooling rehearsal. SQL-рецепт нельзя переносить между системами с другими transactions и locks. Прочитайте generated migration. Узнайте transaction wrapping, applied-state record и поведение после interruption. Файл исполняется в конкретной системе, а не становится безопасным от генерации по schema declaration. Если tool автоматически дополняет действия, включите их в ревью. Иногда короткий исходный запрос приводит к перестроению объекта или изменению ограничения, которого автор не ожидал. Человеку нужно оценивать реальный план исполнения и нужную версию инструмента, а не только декларативный diff модели данных.

Справочник PostgreSQL 18 ALTER TABLE описывает особенности операций и блокировки. Читайте нужную форму, не считая все alterations одинаковыми. Статья не назначает универсальный lock budget и не обещает мгновенность на вашей таблице. Посмотрите engine, характеристики table и workload в разрешённом rehearsal. Объясните limits без выдуманного времени по маленькой fixture. Если масштаб пока не испытан, отдельно запишите semantic readiness и operational readiness. Корректность переноса нескольких учебных строк полезна, но она не устанавливает длительность blocking в нагруженной среде и не заменяет соответствующую проверку условий, на которых команда собирается выполнять настоящий переход.

Используйте этапы при независимых consumers

Рассмотрите добавление new field до удаления old. Тогда приложение адаптируется при сохранении прежнего representation. Это общий expand-and-contract, описанный в руководстве Prisma. Источник объясняет pattern; конкретные commands должны соответствовать вашему toolchain. Не переносите свежую ORM-команду в чужой проект с предположением об одинаковых гарантиях. Версия и backend важны. Если ваш migration tool не поддерживает выбранный способ data transformation, подготовьте подходящий отдельный шаг со своим состоянием и проверкой, а не имитируйте транзакционность добавлением комментария в файл, который фактически запускает несколько независимых операций и процессов.

Назовите stages: schema expansion, compatible application behavior, перенос значений, consistency verification, переключение readers/writers и затем contraction. Реальная система может требовать другого порядка или maintenance window. У каждого этапа есть поддержанное состояние и критерий оценки. Немедленный rename/drop допустим, только если consumers и recovery это позволяют. Стратегию определяют условия, не длина SQL. В review packet полезно показать состояние после каждого завершённого этапа. Тогда при прерывании человек понимает, что уже произошло и что остаётся, а новый агент не начинает процесс сначала, случайно повторяя действие, которое было корректно выполнено до потери ответа предыдущей execution.

Спроектируйте concurrent writes до backfill

Однократное копирование недостаточно, если old writer продолжает обновлять источник. Определите coherence representations: compatible writes, управляемая synchronization или intentional quiescence. Каждая опция требует собственных checks. Не вводите unreviewed trigger или вечный dual-write только ради зелёной fixture. Механизм должен соответствовать архитектуре и scope. Если выбран период остановки записи, нужно установить, какие writers действительно остановлены и как проверяется это состояние. Надпись в приложении не является универсальной блокировкой доступа: job, importer или прямое соединение могут продолжать менять записи, пока пользовательский интерфейс честно показывает maintenance mode основной части системы.

В fixture old consumer меняет note во время backfill. Определите видимое значение для обоих supported readers после этого. Проверьте edit нового consumer, чтобы старый copy не перезаписал свежий текст. Если итог нельзя объяснить, live execution преждевременна. Успех на idle database уже, чем сохранение поведения при заявленных concurrent writes. Полезно управлять порядком событий в тесте: остановить перенос перед записью, выполнить конкурирующее изменение и затем продолжить. Случайный многократный прогон может никогда не попасть в опасное interleaving. Приёмка должна показать нужный порядок воспроизводимо и проверить финальное содержимое, а не только отсутствие исключения в журнале worker.

Создайте представительные безопасные fixtures

Включите обычный текст, empty, missing, Unicode и длинные инструкции в прежнем supported range. Fictional order IDs делают сравнение понятным. Fixture упражняет семантику invariant без настоящих имён и адресов. Если важна production characteristic, смоделируйте её безопасно вместо полного экспорта базы разработчику. Это также улучшает воспроизводимость: небольшой явный набор легче проверить человеку и хранить рядом с тестом. Подготовьте описание назначения каждого необычного случая, чтобы последующий агент не удалил длинную строку или значение с переносом как лишний шум, не понимая, какую реальную границу сохранения данных они проверяют.

Expected values не должны вычисляться migration code. Для rename это точный исходный текст по выбранному missing rule. Один transformation с обеих сторон повторит баг. Сохраните fixture schema version и setup. Маленький semantic rehearsal отличается от scale rehearsal: один проверяет смысл, другой — runtime и operational behavior. Не выдавайте результат одного за другой. Если объёмный набор generated, его происхождение и свойства должны быть известны. Большое количество случайных строк само по себе не гарантирует нужных edge cases. Полезнее явно проверить критические классы данных и отдельно измерить масштаб, сохраняя назначение и ограничения обоих видов наблюдений в итоговом отчёте.

Определите восстановление переноса

Для долгой работы задайте progress record и повтор batch без неправильного изменения уже обработанного. Выберите stable iteration keys. Mutable timestamp может быть плохим cursor при updates. Algorithm зависит от engine и concurrency strategy, поэтому опишите его. Resumability не появляется от имени backfill и счётчика progress. Нужно понимать, в какой момент отметка записывается относительно изменения данных и что будет при потере соединения между ними. Если отметка опережает данные, возможен пропуск. Если отстаёт, повтор должен корректно обработать уже изменённый набор. Конкретное решение требует проверки реального порядка фиксации в используемой системе.

Прервите fixture посредине и продолжите по recorded state. Сравните итог с uninterrupted run. Повторите completed batch, если контракт допускает повтор. Не должно быть duplicates, потери новых значений и unintended empty вместо missing. Batch size и паузы опираются на реальные наблюдения. Не вычисляйте production throughput по нескольким учебным строкам. Важен также конец работы: если progress сообщил полное завершение, отдельная invariant check должна подтвердить, что нужный набор действительно обработан. Счётчик, увеличенный после каждого запроса, может считать попытки, а не успешные изменения. Поэтому финальная проверка состояния сильнее красивого значения сто процентов в конце stdout агента.

Разделите transaction и workflow

Transaction защищает содержащиеся в ней операции, а многоэтапный rollout выходит за один process и commit. Успешная transaction не делает весь workflow atomic. Неудачный application rollout не означает undo schema. Попросите агента описать состояние после каждой failure point. Это реалистичная recovery map вместо предположения, что слово transaction обращает всё в database, application и внешних сервисах. Если этап требует отдельного restart или публикации, его наблюдаемый исход тоже сохраняется отдельно. Между командами может пройти время, за которое появляются новые записи; план должен учитывать такое промежуточное нормальное состояние, а не существовать только для непрерывного идеального запуска без перерывов.

Установите место applied record migration tool и случай disconnect вокруг commit. Recovery сначала читает recorded и actual state перед повтором non-idempotent step. Глава доказательств GrantTap различает request и reported result. Потерянный ответ не устанавливает отказ БД. Используйте штатный inspect и сохраняйте uncertainty до наблюдения. Если инструмент не предоставляет достаточного status, подготовьте безопасную проверку фактической схемы и инварианта. Не выполняйте заново разрушительную команду только потому, что клиент не получил success. Такой повтор может иметь другой эффект на уже изменённом состоянии и ухудшить ситуацию, которую первоначальная операция фактически завершила корректно до обрыва связи.

Отдельная ImageGen-иллюстрация сценария. Она не является свидетельством выполнения предложенных действий и проверок.
ИллюстрацияОтдельная ImageGen-иллюстрация сценария. Она не является свидетельством выполнения предложенных действий и проверок.

Одних row counts недостаточно

Количество строк полезно, но равенство не доказывает сохранение текста каждой записи. Сравните stable IDs и нужные fields с exact values и null semantics. Где требуется, подтвердите неизменность unrelated fields. Count скрывает swapped values, truncation и неверный subset. Агент должен объяснить, какой plausible failure обнаруживает comparison. Для простого rename критерий можно сделать очень конкретным: у каждой нужной записи новое представление соответствует прежнему при согласованном правиле missing, а исходные идентификаторы не изменены. Если transformation сложнее, заранее определите допустимые изменения и отдельный способ проверить их смысл без повторения самой реализации в expected logic.

Verification query остаётся reviewable. Sample называется sample с указанием оставшегося полного check. Не копируйте private rows в чат. Mismatch counts и safe examples помогают ревью, detailed inspection остаётся в нужной среде. Нулевой mismatch относится к выполненному запросу, не ко всем tables и future writes. Сохраните revision и migration identity. Если проверка использует фильтр, объясните его. Ошибка в фильтре может исключить проблемные записи и создать ложный успех при идеально правильном сравнении оставшегося набора. Поэтому scope запроса должен соответствовать scope invariant, а не просто возвращать удобное небольшое число строк, которое легче прочитать на телефоне.

Backup проверяется восстановлением

Success backup command сообщает о команде, не устанавливает restore. Определите recovery objective и isolated destination. Проверьте restored schema, data и нужное application behavior. Не направляйте restore в live среду ради опыта. Target, credentials и ownership должны быть явными. Практикум предлагает rehearsal, не даёт читателю разрешение менять production без соответствующей подготовки. Для удалённого review укажите, где выполнялась проверка и как установлено, что это безопасная цель. Похожее имя базы не является достаточной защитой: перед действием сверяют действительное соединение и предусмотренные ограничения доступа, не раскрывая сами секреты в сводке или журнале команды.

Запишите охват backup, включая external objects, если они важны. Snapshot БД не восстанавливает файлы в другом storage. Timing привязывайте к настоящим измерениям и отличиям live environment. Если restore не испытан, пишите unverified, а не backup available как синоним завершённого восстановления. Мобильный packet указывает evidence без копии базы и secrets. Если restore rehearsal выявил неполный набор, исправьте процесс до сильного заявления о recovery. Сохранённый файл полезен, но его полезность при настоящем отказе определяется возможностью получить требуемое согласованное состояние, а не только существованием архива с ожидаемым расширением в выбранной папке.

Возврат кода не равен восстановлению данных

Source revert не возвращает автоматически прежнюю representation и не обязательно сохраняет новые writes. Перед stage назовите old application, совместимую с нынешними data/schema. В expanded состоянии предыдущий compatible build полезен; после contraction его может уже не быть. Не описывайте rollback одной кнопкой без реальной поддержки полного эффекта. План называет target state и verification. Если новый код успел записать значения, которые старый не понимает, простое переключение binary создаёт новую несовместимость. Этот вопрос следует решить до публикации, а не обнаруживать при срочном восстановлении, когда внимание команды уже ограничено происходящим пользовательским отказом.

Для note-example сохраняйте old representation до подтверждения отказа от неё supported consumers. Если new writes несут непредставимую прежде информацию, reverse transformation — самостоятельная задача. Даже rename требует ясного concurrent-write contract. Recovery drill проверяет старое приложение с той БД, которую оно реально встретит. Успешный startup слабее нужного read/write без потери инструкций. Если compatible recovery невозможен после определённого этапа, обозначьте эту точку заранее. Тогда решение о contraction принимается с пониманием изменившихся вариантов восстановления, а не под впечатлением, что любое изменение остаётся обратимым, пока в Git сохранён прежний commit исходников и можно вернуть старый schema file.

Подготовьте конкретный пакет ревью

Сводка включает invariant, environment, migration ID, stages, rehearsal и recovery state. Укажите schema и data diff. Destructive steps и unresolved consumers выделяются, потому что влияют на решение. Человек с телефоном не должен угадывать drop column по фразе «база обновлена». Завершите reviewable plan и safe rehearsal до нужного финального разрешения. При этом не объявляйте live execution состоявшейся. Состояния prepared, rehearsed, applied и verified имеют разный смысл. Полезно назвать следующую зависимость: например, остаётся подтвердить вывод старого writer или проверить operational budget на подходящем стенде, тогда как семантические fixtures уже прошли.

Сверяйте Task и execution GrantTap. Local fixture одного компьютера не устанавливает изменение production другого. При handoff сохраните identity и stage, чтобы следующий агент не начинал первую команду заново. Глава переноса описывает continuity продукта; database workflow требует собственного inspect state. Сильный итог опирается на наблюдение нужной среды. Если computer временно offline, подготовьте независимую часть работы и оставьте specific pending check. Ожидание связи не превращает proposed migration в applied, а прежняя успешная квитанция другой операции не должна приписываться новой лишь потому, что сообщения имеют похожий текст и появляются рядом в одном интерфейсе.

Удаляйте старое по свидетельствам

Contraction — отдельный stage с acceptance. Подтвердите consumer set и отсутствие либо обработку old writers согласно плану. Отсутствие имени поля в latest source недостаточно при independently deployed clients. Удаление лучше отделить от несвязанного refactor. Если evidence нет, оставьте compatible expanded state намеренно вместо искусственного завершения. Это может быть правильным промежуточным результатом: приложение работает, данные сохранены, а ограничение следующего шага известно. Задача не обязана выглядеть законченной ценой разрушения поддерживаемого пути, которым часть пользователей или jobs всё ещё пользуется в пределах реального продуктового контракта.

После contraction повторите journey и integrity checks. Сохраните настоящий исход и limits. Migration record объясняет не только команды, но основания переходов. Это полезное knowledge для следующего изменения. Агент ускоряет подготовку, чтение и повтор checks, но человеку нужен coherent account semantics и consumers. Syntactically correct SQL может быть неверным product change при скрытых предположениях. Если часть старых клиентов перестаёт поддерживаться намеренно, это самостоятельное решение, которое должно быть известно команде и отражено в подходящем поведении клиента, а не случайный побочный эффект удаления колонки, выявленный только после выхода новой схемы в рабочее окружение.

Сохраните повторяемый rehearsal

Оставьте fixture, invariant checks, interruption recovery и проверенный restore path по необходимости. Не стройте универсальный database administration продукт внутри одной Task. Встройте полезные проверки в existing tooling рядом с владельцем поведения. При смене tools повторите зависимые tests: знакомый filename не переносит гарантию в другой execution mechanism. Для продолжения достаточно понятного входа, результата и причины ограничений. Если rehearsal generated временные данные и процессы, уберите собственный disposable остаток после сохранения нужных свидетельств. Это сохраняет удобство следующего запуска и не смешивает полезный migration artifact с временным каталогом, созданным ради одного проверочного упражнения на компьютере разработчика.

Хороший запрос через GrantTap теперь точен: найти consumers, подготовить expansion, испытать transfer и preserved values до live application и contraction. Итог — инженерное изменение, которое можно оценить, а не уверенный SQL-файл. Он переживает computer change и interruption, потому что invariant, stage и evidence явны. Такой стандарт полезен для любой persistent-data работы агента: команда объясняет, что сохраняется, что меняется и чем установлен recovery. Тогда автоматизация ускоряет действительно проверяемую работу, сохраняя внимание человека для содержательных решений о данных и совместимости вместо принятия каждого шага по одному успешному коду завершения незнакомой команды.

Источники

ДалееОкружение агента без секретов в чате: от настройки до работающего процесса →