|
Publicité ' | |||||||||||||||||||||||
|
|
#1 |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Bonjour à tous,
je tourne en rond depuis un moment sur une problématique de Commit/Rollback sur Talend. Je lis une table source qui contient des informations suivantes: - NUMERO_COMMANDE - NUMERO_LIGNE_COMMANDE - CLIENT - NOM_CLIENT - ARTICLE - LIBELLE ARTICLE - QTE_COMMANDEE - PRIX_UNITAIRE A partir de cette table je dois en alimenter 2 autres: La table COMMANDE: - NUMERO_COMMANDE - CLIENT - NOM_CLIENT La table LIGNE_COMMANDE: - NUMERO_COMMANDE - NUMERO_LIGNE_COMMANDE - ARTICLE - LIBELLE ARTICLE - QTE_COMMANDEE - PRIX_UNITAIRE Le traitement doit se réaliser enregistrement par enregistrement. S'il n'y a pas d'erreur lors de l'insertion dans COMMANDE et LIGNE_COMMANDE je voudrais faire un commit sur l'enregistrement et passer au suivant. S'il y a une erreur lors de l'insertion de l'enregistrement dans COMMANDE ou LIGNE_COMMANDE je voudrais faire un rollback de la ligne en erreur mais continuer le traitement. Merci pour vos propositions. |
|
|
00
|
|
|
#2 |
|
Membre habitué
![]() Inscription : août 2005 Messages : 117 ![]() |
Bonjour,
pourrais-tu indiquer la version de Talend que tu utilises (TIS / TOS et numéro de version) Est-ce vraiment une nécessité ? Si la transaction est au niveau de tout le flux, est-ce vraiment un problème ? As-tu beaucoup de lignes dans le flux source ? Voilà une solution mais je ne te la conseilles pas pour les raisons suivantes : > C'est du bricolage > C'est vraiment pas performant > Il y a un risque d'outOfMemory selon le nombre de thread créés (même en décochant multithread dans le tRunJob). 9a plante chez moi pour quelques milliers de lignes. Après, tu peux toujours jouer sur la JVM ou sur la mémoire allouée à chaque thread (la baisser) pour augmenter tes chances (mais le risque est de se retrouver avec un StackOverflowError à la place). > Job 1 : Lecture source (tOracleInput) --> Main vers un tRunJob (vers Job 2) qui a pour variables les champs de ton flux (Bien penser à décocher l'exécution multithread) > Job 2 : Connection --> Transformation des variables en flux () --> Transformation du flux (tMap) --> Écriture dans tes deux tables (tOracleOutput) --> Commit --> Fermeture connection Je posterai plus tard un screen des jobs. Je vais quand même voir si je ne trouve pas quelque chose de plus pérenne. |
|
|
00
|
|
|
#3 |
|
Membre habitué
![]() Inscription : août 2005 Messages : 117 ![]() |
Bon, j'ai tenté de faire ça en un seul job pour éviter les problématiques citées ci-dessus.
Ça donne quelque chose comme ce que j'ai mis en pièce-jointe. Ça a l'air de fonctionner, mais je n'ai pas accès tout de suite à une base où je peux faire des tests sur ce genre de choses. Si tu as besoin de détails sur la configuration des divers composants. |
|
|
00
|
|
|
#4 |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Bonjour,
merci tetsu no tama pour tes réponses. Je travaille sur TIS avec la version 4.0 de Talend. Oui, je suis obligé de faire un traitement enregistrement par enregistrement. Le projet que je suis en train de traiter est la reprise d'un flux de données issus de Scribe (outil de migration, traitement des données). Les jobs talends développés doivent être iso fonctionnels. Le nombre de lignes dans certains des traitements sera certainement conséquent (> 1 000 000 de lignes dans certains cas). J'ai déjà réussi à me faire un job comme proposé dans ta première solution. (voir pièces jointes). Cette méthode fonctionne parfaitement avec un faible volume de données. Mais elle me pose 2 problèmes et avec ce que tu as dis peut-être 3: - le 1er mais qui n'est pas si grave et que ça me dérange d'avoir 2 Jobs là ou l'ancien produit permettait de tout faire dans un traitement. Bon, c'est un point sur lequel je peux me débrouiller. - le 2ème point est que certaines des tables sources que je traite ont 180 attributs!!! J'ai une 10ènes de lots à reprendre qui sont comme ça, et la perspective de devoir créer 180 variables m'ennuie un peu. - le 3ème, c'est le risque de non performance que tu évoques. Je n'ai pas fait de test avec une forte volumétrie. C'est pour tout ça que je voulais tout faire dans un seul Job. Je vais faire un test sur ta deuxième proposition et je te tiens au courant. Merci |
|
|
00
|
|
|
#5 |
|
Membre chevronné
![]() Inscription : novembre 2004 Messages : 569 ![]() |
Bonjour,
Dans les paramètres du composant tOracleOutput, onglet Advanced settings tu as le paramètres "Commit every " qui est par défaut positionner à 10000. TU peux le mettre à 1. Ceci augmentera la charge coté oracle bien sûr. Mais pour l'utiliser il faut virer le oracleconnect, commit et rollback. Tu peux récupérer les lignes rejeter à partir du OracleOuput. Il a deux flux: main et reject. Moi je les récupère dans un fichier CSV et j'envoie par mail. L'avantage est que ça ne plante pas le job. Mais si en cas d'errer tu veux tout arrêter , tu peux cocher "Die on error" |
|
|
00
|
|
|
#6 |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Bonjour,
Peut-être que la solution pourrait venir de la gestion des erreurs avec les composants tWarning ou tDie. Dans l'exemple que j'ai cité en haut, je pourrai mettre le rollback et le commit après le composant d'insertion sur la table LIGNE_COMMANDE. S'il n'y a pas eu d'erreur (errorCode == null) lors de l'insertion dans les premières tables le COMMIT s'exécute. S'il y a eu une erreur alors on fait le Rollback mais il faudrait remettre le errorCode à null. Est-ce possible? Je ne sais pas trop comment faire car je ne connais pas bien java... Le seul Hic avec cette solution c'est que je ne suis pas sûr de l'ordre d'exécution de talend. Est-ce qu'il va commencer par insérer toutes les lignes du flux dans la première table (COMMANDE) et ensuite toutes les lignes du flux dans la seconde table (LIGNE_COMMANDE) (Dans ce cas là, ma solution du test des erreurs tombe à l'eau) ou va-t-il traiter 1 enregistrement dans COMMANDE, 1 enregistrement dans LIGNE_COMMANDE, etc..? Les tests que j'ai réalisé avec des traces en sortie de chacun des composants me laisse espérer que la deuxième solution est la bonne. Mais rien ne m'assure que cette réaction sera toujours la même. A suivre... |
|
|
00
|
|
|
#7 |
|
Membre habitué
![]() Inscription : août 2005 Messages : 117 ![]() |
Mais ta solution ne garantie pas que la transaction porte sur l'ensemble :
ligne_commande / commande. Seulement que, si les lignes de commandes sont bien insérées, tu envois le flux commande vers le tOracleOutput. Quid si l'insertion de ta commande plante ? |
|
|
00
|
|
|
#8 |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Une piste,
J'essaie de gérer mon commit et mon rollback avec une variable de contexte "codeErreur" qui devrait être mise à jour lorsqu'il y a un rejet sur une des tables où je fais l'insertion. Le principe: - à chaque itération, le composant tjavaflex met la variable de contexte codeErreur à 0 - après chaque insertion, s'il y a rejet, je mets cette variable de contexte à 1 - lors l'itération est terminé je teste ma variable. Si elle est égale à 0 alors commit, si elle est égale à 1 alors rollback. Problème, à chaque passage dans TEST1 ou TEST2 il y a un flux de rejet. Ce qui fait que ma variable est toujours égale à 1, donc rollback à chaque coup. Quelqu'un aurait il une explication, sachant que je ne peux pas mettre mon composant en erreur (je ne veux pas sortir du job). Merci pour votre coup de main. |
|
|
00
|
|
|
#9 |
|
Membre chevronné
![]() Inscription : novembre 2004 Messages : 569 ![]() |
Sur oracle il y a des foreignKey. Tu les positionne sur Commande Line par rapport à commande et client.
Si l'insertion ne passe pas au niveau de commande et client c'est oracle qui rejete la ligne sur lignecommande. Dans Talend tu ne gère pas ça. Juste récupère les lignes rejetées |
|
|
00
|
|
|
#10 |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Bonjour,
Je n'ai pas le droit de modifier la structure de la base de données. |
|
|
00
|
|
|
#11 |
|
Membre habitué
![]() Inscription : août 2005 Messages : 117 ![]() |
atb, ta solution est effectivement très bien mais elle ne permet pas de garantir que la transaction complète s'est bien déroulée.
Si on se base uniquement sur les rejets liés à des erreurs de FK : 1 > insérer les commandes 2 > insérer les lignes de commandes (Rejets si la FK ne correspond pas à une PK de commande) Mais, si un plantage survient au moment de l'insertion des lignes de commandes , alors, tu auras déjà bel et bien inséré une commande incomplète. Si j'ai bien compris le besoin de enricococo40, la transaction doit garantir que l'ensemble : "commande / lignes de commande" est Ok. |
|
|
00
|
|
|
#12 |
|
Membre chevronné
![]() Inscription : novembre 2004 Messages : 569 ![]() |
Alors je ne comprends pas, pourquoi on insert pas dans les tables Commande et client. Tout en récupérant les rejets.
Ensuite on insert dans la table ligne commande. Puis on supprime les lignes de cette dernier, qui correspondent aux lignes rejetées des deux premières tables . Ensuite on supprime, par exemple de la table commande dont les lignes ne sont pas passées. Avec la possibilité d'envoyer par mail les lignes rejetées. A la fin on commit. En utilisant tOracleConnection + tOraclecommit ? |
|
|
00
|
|
|
#13 | |
|
Invité de passage
![]() Coco Enrico Inscription : novembre 2009 Messages : 6 ![]() |
Bonjour,
Citation:
En code grosso modo ça aurait donné ça: -- Ouverture d'un curseur -- Boucle de Lecture du curseur -- Ouverture d'une transaction SQL -- Insertion table 1 -- Maj table 2 -- Insertion ou update table 3 -- Gestion des Exceptions -- Si aucune exception commit -- Sinon Rollback -- Fermeture de la transaction --Retour au début de la boucle J'ai réussi à trouver la façon de faire fonctionner le traitement en remplaçant mon composant tjava par un composant tjavarow juste après les rejets. Ce composant met à jour une variable d'erreur que je teste ensuite pour faire le commit rollback. Cette variable est remise à jour par le tjavaflex à chaque itération. Pour ceux que ça intéresse, l'itération est assez couteuse au niveau de la performance. Dans mon cas, je n'ai pas trouvé le moyen de m'en passer. Le passage par un job/sous job est comme le signalait "tetsu no tama" très pénalisant niveau performance et je suis d'accord avec lui ça fait un peu bidouille... Merci pour votre aide. |
|
|
|
00
|
Copyright © 2000-2012 - www.developpez.com