Восстановление загрузки из SQL Server в Oracle после обрыва VPN
Оборванный VPN оставляет вызывающую сторону в неведении, дошёл ли commit в Oracle. Устойчивый идентификатор пакета позволяет отвечать на вопросы о выгрузке, применении и сверке по одному.
Межбазовый перенос умирает, когда VPN обрывается, а «запусти ещё раз» — не план восстановления. Выгрузка из источника может быть завершена, целевая база могла уже выполнить commit, или ответ просто потерялся на обратном пути. Эти три состояния требуют разных действий, и клиент, знающий только «ошибка», не может их различить.
Решение архитектурное: дайте каждому запуску устойчивую идентичность пакета и позвольте базам данных отвечать на вопросы, а не клиенту гадать.
Что база данных на самом деле гарантирует
SQL Server и Oracle обе обеспечивают атомарность внутри транзакции. Ни одна не даёт атомарности между ними двумя. Потерянное соединение не повреждает базу данных и не вынуждает к ручному откату, потому что сервер сам разрешает свою транзакцию без вас. Ломается знание вызывающей стороны об исходе.
Зафиксировано отдельно означает зафиксировано отдельно. VPN, несущий оба соединения, не сливает два commit в одну единицу работы.
Commit, о котором вы никогда не слышали
Один режим отказа наказывает наивную логику повторов: сервер выполняет commit, а подтверждение так и не доходит до вызывающей стороны. Oracle документирует это как проблему неизвестного исхода и предоставляет для неё Transaction Guard в документации по транзакциям. Ошибка связи не является доказательством того, что отправленный commit не удался, и воспринимать её как доказательство — это путь к двойной публикации пакета. Это различие важнее всего на пути повтора, где у оператора есть только сообщение об ошибке и никакого другого сигнала для действий.
Поэтому шаг восстановления должен читать исход из целевой базы, а не выводить его из текста ошибки.
Дайте переносу идентичность пакета
Каждый запуск получает неизменяемый ID пакета, и целевая база записывает, что она сделала с этим ID. Жизненный цикл состоит из четырёх шагов, и он выглядит одинаково независимо от поставщика:
- Выгрузите идентифицированный, неизменяемый пакет источника с записанной схемой и границей.
- Передайте его в подготовительную область целевой базы и обнаружьте неполное или противоречивое содержимое, прежде чем объявить его готовым.
- Примените его по собственным правилам уникальности или блокировки целевой базы и запишите завершение в той же локальной транзакции.
- Сверьте устойчивый исход через поддерживаемый протокол, прежде чем подтверждать или повторять.
Повторы используют тот же ID. Новый ID на каждую попытку сводит на нет предотвращение дублей, которое вы только что построили; это звучит очевидно, пока обёртка повтора не сгенерирует его автоматически.
ID также даёт вам то, с чем можно сверяться позже, спустя долгое время после исчезновения клиентского процесса.
Заявите пакет, затем примените
Шаг применения должен заявить ID пакета, выполнить бизнес-изменения и записать завершение в одной локальной транзакции. Выполнение проверки и вставки отдельными операторами возвращает гонку, которую вы пытались устранить. Если два работника соревнуются, побеждает ровно одно заявление, а другому сообщают об этом.
Отсутствие записи о завершении не является доказательством того, что выполняющаяся транзакция никогда не сделает commit. Заявление должно сериализовать конкурирующие попытки, либо протокол должен прочитать устойчивый исход до любого решения.
Для этой сериализации используйте поддерживаемый механизм базы данных, а не цикл «проверь и повтори» в коде приложения.
Чего проект всё ещё не может обещать
Подготовка делает работу перезапускаемой и снижает зависимость от одной долгой сессии. Она не создаёт единственный атомарный commit по SQL Server, Oracle и любому внешнему побочному эффекту, который выполняет работа. Если бизнесу это действительно нужно, спроектируйте и квалифицируйте поддерживаемую распределённую транзакцию или процесс сверки, включая то, кому принадлежит работа с неопределённым исходом. Всё более слабое относится к методике сверки, а не к коду переноса.
Примите прерывание в трёх местах: во время переноса, во время применения и после commit, но до подтверждения. Затем проверяйте бизнес-результат, а не сообщение клиента, и позвольте журналу пакетов сказать, незавершена работа, зафиксирована или всё ещё не решена.