Un transfert entre bases de données meurt lorsque le VPN tombe, et « relance-le » n’est pas un plan de récupération. L’extraction depuis la source peut être terminée, la cible peut avoir déjà commité, ou la réponse a simplement pu se perdre sur le chemin du retour. Ces trois états exigent des actions différentes, et un client qui ne connaît que « erreur » ne peut pas les distinguer.

Le correctif est architectural : donnez à chaque exécution une identité de lot durable, et laissez les bases de données répondre aux questions au lieu de laisser le client deviner.

Ce que la base de données garantit réellement

SQL Server et Oracle offrent tous deux l’atomicité à l’intérieur d’une transaction. Aucun ne vous offre l’atomicité entre les deux. Une connexion perdue ne corrompt pas la base de données et n’impose pas non plus de rollback manuel, car le serveur résout sa propre transaction sans vous. Ce qui casse, c’est la connaissance qu’a l’appelant du résultat.

Commité séparément signifie commité séparément. Un VPN qui porte les deux connexions ne fusionne pas deux commits en une seule unité de travail.

Le commit dont vous n’avez jamais entendu parler

Un mode de défaillance punit la logique de nouvelle tentative naïve : le serveur commite, et l’accusé de réception n’atteint jamais l’appelant. Oracle documente cela comme le problème du résultat inconnu et fournit Transaction Guard pour cela dans la documentation des transactions. Une erreur de communication n’est pas la preuve qu’un commit soumis a échoué, et la traiter comme une preuve est la façon dont un lot est publié deux fois. La distinction compte le plus sur le chemin de la nouvelle tentative, où l’opérateur dispose d’un message d’erreur et d’aucun autre signal sur lequel agir.

L’étape de récupération doit donc lire le résultat auprès de la cible plutôt que de l’inférer à partir du texte de l’erreur.

Donnez une identité de lot au transfert

Chaque exécution reçoit un identifiant de lot immuable, et la cible enregistre ce qu’elle a fait de cet identifiant. Le cycle de vie comporte quatre étapes, et il est identique quel que soit le fournisseur :

  1. Extrayez un lot source identifié et immuable avec un schéma et une limite enregistrés.
  2. Transférez-le vers la zone de préparation de la cible et détectez le contenu incomplet ou conflictuel avant de le déclarer prêt.
  3. Appliquez-le selon les règles d’unicité ou de verrouillage propres à la cible et enregistrez l’achèvement dans la même transaction locale.
  4. Rapprochez le résultat durable via le protocole pris en charge avant d’accuser réception ou de réessayer.

Les nouvelles tentatives réutilisent l’identifiant. Un nouvel identifiant par tentative ruine la prévention des doublons que vous venez de construire, ce qui semble évident jusqu’à ce qu’un wrapper de nouvelle tentative en génère un automatiquement.

L’identifiant vous donne aussi quelque chose contre quoi rapprocher plus tard, longtemps après la disparition du processus client.

Revendiquez le lot, puis appliquez

L’étape d’application doit revendiquer l’identifiant de lot, effectuer les changements métier et enregistrer l’achèvement dans une seule transaction locale. Faire la vérification et l’insertion en instructions séparées réintroduit la course que vous cherchiez à supprimer. Si deux workers se disputent, exactement une revendication gagne et l’autre en est informé.

Un enregistrement d’achèvement absent n’est pas la preuve qu’une transaction en cours ne commitera jamais. La revendication doit sérialiser les tentatives concurrentes, ou le protocole doit lire le résultat durable avant de décider quoi que ce soit.

Utilisez le mécanisme pris en charge par la base de données pour cette sérialisation plutôt qu’une boucle vérifier-puis-répéter dans le code applicatif.

Ce que la conception ne peut toujours pas promettre

La préparation rend le travail redémarrable et réduit la dépendance à une seule session de longue durée. Elle ne crée pas un commit atomique unique à travers SQL Server, Oracle et tout effet secondaire externe que le travail produit. Si le métier en a vraiment besoin, concevez et qualifiez une transaction distribuée prise en charge ou un processus de rapprochement, y compris qui possède le travail au résultat incertain. Tout ce qui est plus faible appartient à un runbook de rapprochement, pas au code de transfert.

Acceptez l’interruption à trois endroits : pendant le transfert, pendant l’application, et après le commit mais avant l’accusé de réception. Vérifiez ensuite le résultat métier plutôt que le message du client, et laissez le registre des lots dire si le travail est incomplet, commité ou encore non résolu.

Articles similaires