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

Administration Oracle Discussion :

insertion, violation de contraint et commit


Sujet :

Administration Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2003
    Messages : 92
    Par défaut insertion, violation de contraint et commit
    Bonjour à tous,

    Voila mon petit problème j'ai une application qui tourne sur plusieurs poste et qui alimente une même base (oracle 10g)

    le principe est simple:
    à partir de fichier, l'application doit créer des "rubriques" dans la table rubriques
    si une rubriques existe déjà, on met juste à jour un champ dt_maj

    or la création d'une rubrique peut mettre bcp de temps (plusieurs traitement à effectuer avant de commiter)

    voila donc ce qui se passe

    1- appli1 du poste1 crée rubrique1 (sans commit) et continue son traitement, si tous les traitement sont ok, on commit la transaction sinon on fait un rollback

    2- juste aprés appli2 du poste2 recoit l'ordre de créer rubrique2, mais comme appli1 n'a pas commité, appli2 essai alors de créé rubrique2 (au lieu de la mettre à jour) mais celui-ci recoit une erreur ORA-00001: unique constraint violated

    3- à cause de l'erreur, appli fait un rollback

    4- appli1 a fini son traitement et commit (si pas d'erreu sinon rollback)

    Premièrement est ce normal de recevoir l erreur de violation de contraint alors que la premiere appli n'a pas commité
    Secondo Que peut on proposer pour ce type de problèmatique ?


    Merci de votre aide

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2003
    Messages : 92
    Par défaut
    En fait, je me pose la question de savoir si il y'a pas un problème de conflit d'insertion entre ces deux application vu que pour chaque appli entre le début de la transaction et le commit, il peu se passer 4/5 minute

    Merci pour votre aide prochaine

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Février 2006
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3 437
    Par défaut
    Pour répondre précisément à vos questions, il faudrait savoir comment sont gérées les colonnes qui composent la clé primaire ou unique qui provoquent l'erreur: ces valeurs à insérer sont-elles entrées par l'utilisateur, calculées par le code applicatif et si oui comment ? Essayez de poster un scénario SQL complet avec les 2 sessions qui simule ce qui ce passe dans l'application: ceci devrait permettre de comprendre ce qui ce passe exactement.

    Votre problème ressemble à un problème classique de non utilisation d'une séquence qui permet de générer un numéro dont Oracle est censé garantir l'unicité pour être utilisé comme clé primaire ou clé unique. Voir le tutoriel http://fadace.developpez.com/oracle/sequences/.

  4. #4
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    Bonjour,

    En première analyse, je pense que le scénario suivant se produit :

    La base est dans le niveau d'isolation READ_COMMITED (mode par défaut).

    dans ce mode :
    A fait un insert des valeurs (KEY1,VALUE1) mais ne commit pas.
    B fait un insert des valeurs (KEY1,VALUE2) car l'ordre select sur KEY1 ne retourne rien. En effet dans le mode READ_COMMITTED, seule les transactions committées sont prises en compte. Pour B, la clé KEY1 est donc dispo La transaction n'est pas rejetée car A n'a toujours pas commité. La transaction B est en fait en attente du commit/rollback de A. Si A rollback, la transaction B va être acceptée si A commit, la transaction va être rejetée.
    La suite, tu la connais : A commit et donc la transaction de B est rejetée à juste titre.

    La réponse à ta première question est donc que la transaction B est rejetée mais seulement après le commit de A. Elle est mise en attente tant que A n'a pas commité.

    Tu peux tenter de verouiller les enregistrements de ta table par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     select * from table for update
    Dans ce cas de figure, lorsque A effectue sa mise à jour, toutes les autres transactions (même les ordres select) sur la table sont mises en attente du commit/rollback. Dans ce cas de figure lorsque B va effectuer le select , il verra la clé KEY1 (car l'ordre select sera en attente du commit) et effectuera donc un update plutôt qu'un insert.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2003
    Messages : 92
    Par défaut
    Bonjour et bonne année tous

    mongolic, c'est exactement ça mon problème et ton jeu de test explique mon problème

    Cependant la solution avec le select for update ne fonctionne pas, car il ne bloque pas les select comme tu le dis et c'est bien dommage car ça aurait résolu mon problème

  6. #6
    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,
    Citation Envoyé par elkamaro Voir le message
    1- appli1 du poste1 crée rubrique1 (sans commit) et continue son traitement, si tous les traitement sont ok, on commit la transaction sinon on fait un rollback

    2- juste aprés appli2 du poste2 recoit l'ordre de créer rubrique2, mais comme appli1 n'a pas commité, appli2 essai alors de créé rubrique2 (au lieu de la mettre à jour) mais celui-ci recoit une erreur ORA-00001: unique constraint violated
    Par "n'a pas commité" tu veux dire que appli1 a rollbacké, c'est bien ça ?
    Dans ce cas, il suffit de tester l'erreur ORA-00001 et dans ce cas retourner en 1
    Et là appli2 va lui-même créer la rubrique puisque appli1 aura rollbacké

    Mais tout ce scénario peut proser des problèmes de performances: toutes les transactions concurrents vont être sérialisées sur la rubrique.

    Cordialement,
    Franck.

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Comment générez-vous vos clefs ?
    Avec des séquences ou avec des select max(KEY) from MaTable ?

  8. #8
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    elkamaro, es tu sûr de faire le select sur toutes les lignes de la table (sans clause where):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from table for update
    Lorsque tu fais un select for update, oracle vérouille les enregistrements retournés par le select. Ce que je te propose est de faire un verouillage sur toute la table avant de faire ta tambouille :

    1 select * from table for update -- verouillage de la table
    2 select * from table where code ='KEY' --test d existence pour decision : insert ou update
    3 ordre insert ou update
    3 commit -- ce qui libère tous les enregistrements de la table

  9. #9
    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
    mongolic,
    un select for update va vérouiller tous les enregistrements existants, mais ne va pas protéger d'un insert en cours. C'est différent d'un lock table.
    Il n'y a qu'un insert qui peut bloquer un autre insert (de la même valeur, et parce qu'il y a un index unique -> c'est alors l'entrée d'index qui est vérouillée)

    elkamaro,
    tu peux peut-être regarder la fonction dbms_lock pour faire un vérouillage un peu plus 'custom'.

    Cordialement,
    Franck.

  10. #10
    Membre confirmé
    Inscrit en
    Août 2009
    Messages
    107
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Août 2009
    Messages : 107
    Par défaut
    ok pour ton explication, je ne suis pas spécialiste et je me trompe peut-être. Mais je ne vois pas pourquoi çà ne marcherait pas :
    Si une transaction est en cours, cela veut dire qu'il y a eu un select * for update en cours,. Donc toute autre transaction, ne passera pas l'étape 1 puisque le select * for update sera mis en attente par celui de la 1ere transaction.
    Est ce que je me trompe ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. INSERT et violation de contrainte Unique Key
    Par calagan99 dans le forum SQL
    Réponses: 14
    Dernier message: 26/08/2013, 14h48
  2. Insertion de données et violation de contrainte de clé primaire
    Par Krapo_Lazer dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 13/06/2008, 12h51
  3. [hibernate] Violation de contrainte unique
    Par miyabi dans le forum Hibernate
    Réponses: 1
    Dernier message: 07/06/2006, 14h52
  4. [Oracle] Script création Table, violation de contraintes
    Par boudou dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/02/2006, 13h47
  5. Réponses: 2
    Dernier message: 13/02/2006, 11h13

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