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

Oracle Discussion :

Trouver qui lock un enregistrement (pas bloque)


Sujet :

Oracle

  1. #1
    Membre du Club Avatar de schnourf
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Points : 43
    Points
    43
    Par défaut Trouver qui lock un enregistrement (pas bloque)
    Bonjour,

    dans la boite ou je suis, pour empecher que les utilisateurs modifient la même ligne en même temps, nous faisant un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM TABLE1 WHERE TBL_ID = 12345 FOR UPDATE NOWAIT
    Dans notre application nous avons un bouton modifier que met l'application en mode modification et donc sur ce bouton on fait le "SELECT FOR UPDATE NOWAIT" -> si on recoit un exception c'est que c locker sinon on passe en mode modification.

    Quand l'utilisateur reçoit l'exception, j'aimerai bien afficher un message d'erreur lui disant que tel ou tel autre personne est entrain de modifier pour cela j'ai fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	select substr(object_name,1,20) "Object",
      substr(os_user_name,1,10) "Terminal",
      substr(oracle_username,1,10) "User",
      OBJECT_TYPE "Type",  
      A.OBJECT_ID, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#,
      dbms_rowid.rowid_create ( 1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#)
    FROM
      SYS.V_$LOCKED_OBJECT A,
      SYS.ALL_OBJECTS B,
      SYS.V_$SESSION c
    WHERE
      A.OBJECT_ID = B.OBJECT_ID AND
      C.SID = A.SESSION_ID
    et j'ai remarqué que A.OBJECT_ID est different de ROW_WAIT_OBJ#, ce qui à mon sens est normal vu que personne n'est bloqué et en attente.

    A.OBJECT_ID represente TABLE1 tandis que ROW_WAIT_OBJ# une autre TABLE X

    Ceci reprensente un probleme car je ne peux pas recupere le rowid de la ligne lockée dans TABLE1 car dbms_rowid.rowid_create ( 1, ROW_WAIT_OBJ#, ROW_WAIT_FILE#, ROW_WAIT_BLOCK#, ROW_WAIT_ROW#) me donne le ROWID dans TABLE X.

    Est-ce que vous avez une autre solution à me proposer ??

    Merci beaucoup

  2. #2
    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
    Points : 3 597
    Points
    3 597
    Par défaut
    A.OBJECT_ID represente TABLE1 tandis que ROW_WAIT_OBJ# une autre TABLE X
    J'ai fait un petit test avec la 10.2.0.2 sur XP et je trouve bien que ROW_WAIT_OBJ# identifie dans DBA_OBJECTS la table dont la ligne est verrouillée et sur laquelle il y attente.

    Pourquoi faire un jointure avec SYS.V_$LOCKED_OBJECT et SYS.ALL_OBJECTS ? Je ferais plutôt une jointure seulement avec ALL_OBJECTS.

    J'ai un doute sur l'algorithme utilisé ROW_WAIT_ROW# est seulement valide si une transaction attend sur une autre transaction. Avec NOWAIT, il n'y a pas d'attente

    ROW_WAIT_ROW# NUMBER Current row being locked. This column is valid only if the session is currently waiting for another transaction to commit and the value of ROW_WAIT_OBJ# is not -1.
    Merci de préciser la version exacte d'Oracle utilisée.

  3. #3
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    Je crois que pour garantir accès unique au enregistrement (éventuel affichage d'utilisateur modifiant à l'heure actuelle), creation de propre "LOCKTAB" table est la meilleur solution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LOCKTAB
      id number
      sessionid number
      lockdate date
      utilisateur number
      ...
    Si l'utilisateur veut modifier la ligne, il devrait insérer dans LOCKTAB tout d'abord. Est au fin de mode modification, il devrait effacer de LOCKTAB.
    Beaucoup de travail, beaucoup de problèmes, mais on peut éviter V_$*LOCK*.

    Votre avis?

    DAB

  4. #4
    Membre du Club Avatar de schnourf
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Points : 43
    Points
    43
    Par défaut
    Bonjour, tous d'abord pour repondre a Pifor

    La version d'oracle de 10G release 2
    Ensuite pour moi c'est clair que avec NOWAIT, il n'y a pas d'attente, et que je ne puisse pas utilisé ROW_WAIT_ROW#

    Mais il doit bien y avoir un moyen de trouver la ligne lockée, sans passer pas une table intermediaire comme le propose DAB.cz

    Je vais te montrer ce que je fais

    A partir de mon application (.NET 2.0) je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from vorschlag where vor_id = 12345 for update nowait
    Ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select a.OBJECT_ID, object_name, A.SESSION_ID from
    V_$LOCKED_OBJECT A, ALL_OBJECTS B
    where A.OBJECT_ID = B.OBJECT_ID
    and oracle_username = 'EDV_1'
    me donne ce resultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    OBJECT_ID   OBJECT_NAME   SESSION_ID
    63311          VORSCHLAG     133
    ce qui est correct.

    si je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select OBJECT_ID, object_name, ROW_WAIT_OBJ#
    from V_$SESSION, ALL_OBJECTS
    where ROW_WAIT_OBJ# = OBJECT_ID (+)
    and username = 'EDV_1'
    j'obtiens
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    OBJECT_ID  OBJECT_NAME  ROW_WAIT_OBJ#
    null            null                 88918
    quand je fait mon select for update nowait à partir de TOAD, ROW_WAIT_OBJ# à la valeur -1;

    voila si ça peut aider quelqu'un a comprendre le probleme

  5. #5
    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
    Points : 3 597
    Points
    3 597
    Par défaut
    Mais il doit bien y avoir un moyen de trouver la ligne lockée, sans passer pas une table intermediaire comme le propose DAB.cz
    Je ne crois pas qu'il y a de moyen simple de faire ça avec des vues V$ car:
    • les verrous posés sur des lignes sont écrits par Oracle dans les blocs des données et non dans une structure spécifique de la SGA
    • V$LOCK enregistre les demandes de verrous sur des lignes au niveau de la table concernée et non au niveau des lignes: si vous verrouillez 10 lignes différentes d'une même table en exclusif, vous n'aurez qu'une seule ligne dans V$LOCK (et non 10).

  6. #6
    Membre du Club Avatar de schnourf
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Points : 43
    Points
    43
    Par défaut
    Ok, donc soit je passe par une table intermediare, soit je mentionne dans le message d'erreur tout les utilisateurs qui lockent quelque chose (il n'y en a jamais plus que 5, en général 1-2).

    Merci quand même.

  7. #7
    Membre du Club Avatar de schnourf
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Points : 43
    Points
    43
    Par défaut
    C'est quand même dommage qu'il n'y pas de table V$ qui donne ce genre de renseignements.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 1
    Points : 1
    Points
    1
    Par défaut La requête permettant de trouver les enregistrements réservés par un utilisateur
    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
    31
    32
    33
    select 
      l.type,
      s.sid HOLDING_SESSION,
      s.serial# SESSION_SERIAL,
      s.osuser,
      s.row_wait_obj# ROW_WAIT_OBJ,
      s.row_wait_file# ROW_WAIT_FILE,
      s.row_wait_block# ROW_WAIT_BLOCK,
      s.row_wait_row# ROW_WAIT_ROW,
      o.owner,
      o.object_name,
      dbms_rowid.rowid_create( 1, o.DATA_OBJECT_ID, s.ROW_WAIT_FILE#, s.ROW_WAIT_BLOCK#, s.ROW_WAIT_ROW#) DATA_ROWID,
      rtrim(ltrim(s.osuser))||' (dbuser '||rtrim(ltrim(s.username))||') sur le poste '||rtrim(ltrim(s.machine)) HOLDING_OSUSER,
      substr (c.sql_text, 1, 4096) SQL,
      substr (pc.sql_text, 1, 4096) PREVIOUS_SQL
    from v$lock l, 
      v$session s, 
      v$process p, 
      sys.dba_objects o, 
      v$open_cursor c,
      v$open_cursor pc,
      nls_session_parameters nls
    where l.sid = s.sid 
      and o.object_id (+) = l.id1 
      and c.hash_value (+) = s.sql_hash_value 
      and c.address (+) = s.sql_address 
      and pc.hash_value (+) = s.prev_hash_value
      and pc.address (+) = s.prev_sql_addr
      and s.paddr = p.addr 
      and l.type = 'TM'
      and nls.parameter = 'NLS_NUMERIC_CHARACTERS'
      and s.lockwait is NULL
    ;
    Avec les informations owner, object_name et rowid, vous pouvez requêter la table concernée ou faire une fonction qui vous retourne la donnée en automatique:
    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
    function sys.f_trouve_data(
      p_owner ALL_OBJECTS.OWNER%TYPE,
      p_object all_objects.object_name%TYPE,
      p_rowid ROWID
    ) return varchar2 is
      w_retour varchar2(4096) ;
      w_sql varchar2(4096) ;
      w_dq varchar2(2) := '''' ;
    begin
      w_sql := 'SELECT substr('||w_dq||p_owner||'.'||p_object||' [début - ' ;
      for i in (
        select column_name
        from all_tab_columns
        where owner=p_owner
        and table_name=p_object
      ) loop
        w_sql := w_sql||i.column_name||': '||w_dq||'||'||i.column_name||'||'||w_dq||' - ' ;
      end loop ;
      w_sql := w_sql||' fin ]'||w_dq||', 1, 4096) ' ;
      w_sql := w_sql||' from '||p_owner||'.'||p_object||' where rowid = '||w_dq||p_rowid||w_dq ;
      --return w_sql ;
      EXECUTE IMMEDIATE w_sql
        INTO w_retour
      ;
      return(w_retour) ;
    exception
      when others then return(w_sql) ;
    end ;
    /
    Bon usage.

  9. #9
    McM
    McM est déconnecté
    Expert éminent

    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
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Jérôme, peux-tu éditer ton message et mettre des balises CODE (le # dans le menu d'édition).

    De plus ta requête me parait bizarre. Ta construction de ROWID est basée sur des colonnes de V$SESSION .. donc 1 seule ligne par session.

    Moi ce que j'ai fait pour récupérer le bloqueur est un peu compliqué (Je récupère le ROWID de ce que je veux modifier, je lance par procédure un SELECT FOR UPDATE WAIT 30, et j'ai sur ma BDD un job qui tourne toutes les 10 secondes qui vérifie les sessions en attente en vérifiant la vue DBA_WAITER

  10. #10
    Expert éminent
    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 : 53
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Points : 6 446
    Points
    6 446
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    L'info n'est pas dans des V$ (V$LOCKED_OBJECT montre les verrous tables mais là on parle de verrous lignes) sauf au moment de l'attente. Mais là il n'y a pas d'attente. Ce qu'il faudrait, c'est attendre un peu et voir dans v$session_wait_history les paramètres du dernier "enq: TX" qui donnent l'id de transaction, puis v$transaction, v$session pour avoir plus d'info sur le user.

Discussions similaires

  1. Edition de graphe qui ne s'enregistre pas
    Par nenette69 dans le forum IHM
    Réponses: 1
    Dernier message: 11/03/2013, 22h21
  2. Réponses: 1
    Dernier message: 10/09/2010, 18h05
  3. [AC-2003] [FORMULAIRES] Champs de textes qui ne s'enregistrent pas
    Par Morgo dans le forum IHM
    Réponses: 4
    Dernier message: 29/04/2010, 17h09
  4. [AC-2007] champ qui ne s'enregistre pas
    Par pepsister dans le forum IHM
    Réponses: 27
    Dernier message: 12/04/2010, 10h26
  5. [MySQL] Date qui ne s'enregistre pas
    Par philippef dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 18/04/2006, 21h02

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