IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Comment empêcher deux appels simultanés d'une fonction


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 29
    Par défaut Comment empêcher deux appels simultanés d'une fonction
    Bonjour,

    Notre applicatif dispose d'un package permettant de gérer les différentes numérotations de nos objets métiers (tiers, contrat, etc...). Ce package s'appuie sur une table NUMEROTATION, dont une fonction permet de récupérer une nouvelle numérotation en incrémentant une colonne (VAL_COURANTE). Le commit de la transaction se fait lorsque le tiers, ou le contrat est enregistré.

    Lors d'un appel unique cela fonctionne très bien. Cependant lors de 2 appels simultanés et commit sur chaque session à la suite de ces 2 appels, le numéro retourné est le même, et la colonne VAL_COURANTE a été incrémenté qu'une fois.

    La première résolution a été d'ajouter un PRAGMA AUTONOMOUS_TRANSACTION;afin de commiter la modification de la table NUMEROTATION, lors de l'appel à la fonction de récupération d'un nouveau numéro, sans pour autant commiter l'intégralité de la création de l'objet métier.

    Encore une fois dans le cadre de test solo, cela a résolu le problème principal, mais il reste un point de détail, qui est le sujet de ce topic. En effet, il peut arriver, certes, très rarement, que la procédure puisse être appeler simultanément, et que des insert ou update se fasse avant le commit sur chaque session.

    Est-il possible lors de l'appel sur 2 sessions différentes, de mettre en attente l'appel de la fonction, tel que le ferait un mutex dans d'autre langage de programmation?

    En gros, voila ce que j'aimerai, en remplaçant les TODO :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    CREATE OR REPLACE PACKAGE BODY GESTION_NUMEROTATION AS
     
        FUNCTION SUIVANT(pTYPE_NUM NUMEROTATION.TYPE_NUM%TYPE,
                         pNUM_SOC NUMEROTATION.NUM_SOC%TYPE,
                         pID_CI NUMEROTATION.ID_CI%TYPE := NULL,
                         pCD_PR NUMEROTATION.CD_PR%TYPE := NULL,
                         pCD_TT NUMEROTATION.CD_TT%TYPE := NULL,
                         pID_INT NUMEROTATION.ID_INT%TYPE := NULL,
                         pANNEE_NUM NUMEROTATION.ANNEE_NUM%TYPE := NULL,
                         pMOIS_NUM NUMEROTATION.MOIS_NUM%TYPE := NULL) RETURN VARCHAR2 IS
     
        PRAGMA AUTONOMOUS_TRANSACTION;
     
            -- Var de ma fonctions
     
        BEGIN
            -- TODO : Mutex début
     
                -- Code de la fonction
     
                commit;
            -- TODO : Mutex fin
     
     
        EXCEPTION
        WHEN OTHERS THEN
            rollback;
            -- TODO : Mutex fin
        END SUIVANT;
    END GESTION_NUMEROTATION;

  2. #2
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Tu peux faire un select for update de ta table numérotation.
    Comme ça tu bloque l'enregistrement tant que tu n'as pas commité.

  3. #3
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Citation Envoyé par Tonyryu Voir le message
    ...La première résolution a été d'ajouter un PRAGMA AUTONOMOUS_TRANSACTION;afin de commiter la modification de la table NUMEROTATION, lors de l'appel à la fonction de récupération d'un nouveau numéro, sans pour autant commiter l'intégralité de la création de l'objet métier.

    ...
    Relisez attentivement le chapitre 9 Data Concurrency and Consistency dans Oracle Database Concepts. Essayez de bien comprendre le mécanisme de multiversion consistency model sinon des mauvaises surprises vous attentent à chaque pas!

    [Edit]
    Analysez attentivement votre mécanisme basé sur table NUMEROTATION; il peut constituer un point d’étranglement important dans votre application dans certaines conditions.
    [/Edit]

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 9
    Par défaut
    Pourquoi ne pas utiliser une séquence oracle et faire appel à cette séquence via un select sequence.nextval from ...
    Ceci résoudrait le problème d'attribution de numéro et la gestion de sequence est à toute épreuve. Attention cependant, à chaque appel de nextval, le numéro est incrémenté, qu'il soit utilisé ou pas.

  5. #5
    Expert confirmé
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    C'est effectivement la séquence la seule solution performante et scalable.
    Citation Envoyé par ARAGONIS Voir le message
    Attention cependant, à chaque appel de nextval, le numéro est incrémenté, qu'il soit utilisé ou pas.
    Ce sera de toute façon le cas aussi de la fonction en autonomous transation.

    Cordialement,
    Franck

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 29
    Par défaut
    La gestion de la numérotation a été spécialement développée pour laisser le client paramétrer ses propres numérotations, et donc et surtout ne plus avoir a créer de nombreuses séquences.

    Dans le contexte métier, pour chaque nouveau produit le client créé un nouveau template de numérotation pour la partie contrat et la partie sinistre. On aurait pu effectivement créer une séquence dynamiquement, mais nous avons pris le parti-pris de ne pas les utiliser.

    Comme le précise Pachot, pour l'incrémentation systématique, même si pas utilisée, avec l'utilisation du PRAGMA AUTONOMOUS_TRANSACTION; dans la fonction Suivant, cette contrainte est identique en cas d'erreur de création d'un tiers ou contrat

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2010
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 412
    Par défaut
    Bonjour,

    Perso j'ai toujours pas compris ce que vous vouliez faire exactement. AMHA, le Autonomous transaction ne correspond qu'a quelques cas d'utilisations, et la plus part du temps ce n'est rien de plus qu'un patch qu'on applique sans vraiment comprendre pourquoi ca fonctionne.

    Mais bon, pour revenir a ce dont j'ai compris de votre question, il y a DBMS_LOCK.
    Vous pouvez donc mettre un mutex au debut de votre procedure, et le relacher a la fin (comme si votre fonction etait synchronized en java).
    Mettre un verrou ca peut ralentir tout les gens qui veulent utiliser cette procedure, mais des fois il faut.

    Pour le code de la fonction, si c'est jsute une incrementation, si vous faites un select genre pour recuperer la plus grande valeur il y a peut-etre moyen de faire autrement. Voir la question du 19 Juin sur plsqlchallenge.com en utilisant le create or replace context. (c'est une idee, c'est peut-etre a essayer)

Discussions similaires

  1. Comment simplifier l'appel répétitif d'une fonction paramétrée ?
    Par Tendhor57 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 13/03/2013, 08h02
  2. Réponses: 1
    Dernier message: 23/10/2008, 17h58
  3. Réponses: 8
    Dernier message: 02/02/2006, 18h13
  4. Réponses: 4
    Dernier message: 01/07/2004, 19h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo