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

Requêtes PostgreSQL Discussion :

Trouver le propriétaire d'un lock [9.1]


Sujet :

Requêtes PostgreSQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 861
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 861
    Billets dans le blog
    1
    Par défaut Trouver le propriétaire d'un lock
    Bonjour

    J'ai développé une appli avec datas stockées dans une bdd Postgres. Dans cette appli (multiutilisateurs), chaque utilisateur a accès aux datas qui apparaissent dans une fenêtre. Il peut donc les modifier à la volée et valider la modif via un bouton "modifier".
    Et donc là j'ai voulu protéger 2 utilisateurs qui auraient l'idée de modifier la même data. J'ai donc procédé ainsi: dès que le premier modifie la valeur, je pose un lock via un select for update. Et si le second modife ladite valeur, la prise du lock remonte une exception que je récupère et je lui indique que la data est déjà en train d'être modifiée.

    Donc ça ça marche super. Mais j'aimerais faire encore mieux et lui indiquer par qui elle est modifiée.
    Et là est ma question: y a-t-il moyen de remonter la chaine et arriver au nom de l'utilisateur ayant posé un verrou sur une ligne X d'une table Y ? J'ai un peu regardé pg_lock mais c'est assez obscur...

    Merci
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Par défaut
    Bonjour,

    Tu éviterais ces soucis en te reposant sur les transactions qui sont prévues pour ça et qui évitent de se battre avec des verrous.

    [EDIT] :

    Pour le mode d'isolation (ça doit pouvoir se paramétrer sinon) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    BEGIN;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
    -- tes requêtes
    COMMIT;
    Tu n'échapperas pas à mon avis à une surcouche pour savoir quel est l'utilisateur qui à modifié l'objet. Ils pourraient d'ailleurs être 3 sur la bête et tu auras juste "ERROR: could not serialize access due to concurrent update". Tu dois pouvoir faire des choses en récupérant l'identifiant de la transaction courante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT txid_current();

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 861
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 861
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bretus Voir le message
    Bonjour,

    Tu éviterais ces soucis en te reposant sur les transactions qui sont prévues pour ça et qui évitent de se battre avec des verrous.

    [EDIT] :

    Pour le mode d'isolation (ça doit pouvoir se paramétrer sinon) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    BEGIN;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
    -- tes requêtes
    COMMIT;
    Salut et merci de ta réponse mais ça, vois-tu, je ne pense pas pouvoir l'appliquer.
    Il faut comprendre le fonctionnement de l'appli: sur une page s'affiche à droite toutes les lignes de ma table en un bref résumé. Et à gauche s'affichent, pour chaque ligne, tous les champs qui arrivent dans des zones d'édition.
    Donc l'utilisateur fait dérouler la table par la zone de droite et visualise ses infos. Mais s'il veut en modifier une, il peut aller dans la ou les zones adéquates de gauche et les modifier.
    A ce moment là, chaque zone étant connectée à un slot (je suis avec Qt), je détecte la modification et j'active le bouton "modifier" qui permet de valider les modifs.
    MAIS l'utilisateur n'est pas obligé de valider les modifs. Il peut, s'il le désire, sélectionner une autre ligne de la table sur la page de droite (voire même fermer la fenêtre). Dans ce cas les modis qu'il a faites mais non validées sont perdues. Et s'il les valide, alors je renvoie les infos modifiées dans la table via un update.

    Donc je ne vois pas trop comment mettre un begin transaction pour une transaction qui n'est en fait pas vraiment commencée. Pour moi, elle commence quand je détecte une modif dans les champs (là je pose mon lock). Et lors de l'update (qui est situé bien autre part dans mon code vu que c'est de l'évènementiel) l'update+commit libère alors le lock. Et si un autre utilisateur ne fait que parcourir la table sans entrer dans les champs d'édition, je ne veux pas qu'il soit gêné même s'il arrive sur la ligne en cours de modifs...

    Citation Envoyé par bretus Voir le message
    Tu n'échapperas pas à mon avis à une surcouche pour savoir quel est l'utilisateur qui à modifié l'objet
    Si je peux pas ou si c'est trop compliqué c'est pas grave. C'était juste pour améliorer l'ergonomie générale. Ca marche déjà très bien...

    Citation Envoyé par bretus Voir le message
    . Ils pourraient d'ailleurs être 3 sur la bête
    Ah pas possible. Un seul prend le verrou et c'est son nom que je veux. Même s'il y en a 15 autres qui sont sur la même data, c'est le nom de celui qui a le verrou qui doit remonter...

    Citation Envoyé par bretus Voir le message
    Tu dois pouvoir faire des choses en récupérant l'identifiant de la transaction courante :
    Une info que je ne connaissais pas. Merci
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Par défaut
    Trouver qui bloque quelle table semble possible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT c.relname,a.usename,l.objid FROM pg_locks l, pg_class c, pg_stat_activity a WHERE l.relation = c.oid AND a.procpid = l.pid ;
    Je n'arrive pas à voir qui bloque quelles lignes...

    Au pire, une colonne locked_by?

  5. #5
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 955
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 955
    Par défaut
    Citation Envoyé par bretus Voir le message
    Tu éviterais ces soucis en te reposant sur les transactions qui sont prévues pour ça et qui évitent de se battre avec des verrous.
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    BEGIN;
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;
    -- tes requêtes
    COMMIT;
    Non le mode d'isolation serializable n'a rien à voir avec la gestion des verrous pessimistes.
    C'est bien select for update qu'il faut utiliser.
    Citation Envoyé par Sve@r Voir le message
    Donc je ne vois pas trop comment mettre un begin transaction pour une transaction qui n'est en fait pas vraiment commencée. Pour moi, elle commence quand je détecte une modif dans les champs (là je pose mon lock). Et lors de l'update (qui est situé bien autre part dans mon code vu que c'est de l'évènementiel) l'update+commit libère alors le lock.
    Par contre la transaction commence bien dès le select for update (qui ne bloquera pas les futurs lecteurs de la ligne de part l'architecture MVCC de postgre). Si l'utilisateur ne fait en fait aucune modification il faudra bien aller libérer le verrou par un rollback (ou un commit).

    Concernant le nom de l'utilisateur qui bloque la ligne, je ne connais pas postgre mais la BDD ne connait que les utilisateurs de la base donc si les utilisateurs de l'appli se connectent tous via un user base différent, ça doit être possible.
    Si à contrario tous les utilisateurs de l'appli passent par un user générique pour se connecter à la base, côté BDD c'est une session de ce user qui bloquera une autre session (aucun moyen de connaître l'utilisateur en question) il faut donc le gérer applicativement.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Par défaut
    Il me semble qu'il n'est pas raisonnablement possible de lister les verrous portant sur des lignes, sans même parler d'en trouver le propriétaire.

    Voir ce passage de la doc:
    ( http://www.postgresql.org/docs/9.2/s...-pg-locks.html )
    Although tuples are a lockable type of object, information about row-level locks is stored on disk, not in memory, and therefore row-level locks normally do not appear in this view. If a transaction is waiting for a row-level lock, it will usually appear in the view as waiting for the permanent transaction ID of the current holder of that row lock.
    A propos de la seconde phrase, il ne doit pas y avoir de telle transaction dans ton cas puisque le SELECT FOR UPDATE doit se faire en mode NOWAIT et donc échoue si la ligne est déjà verrouillée. Pour trouver le "current holder of that row lock", il faudrait donc créer une transaction dans le seul but de la faire attendre sur le verrou, mais via une autre connexion car il faudrait simultanément faire la requête qui va bien sur pg_lock. Autant dire une belle usine à gaz...

    Le fait que ce type de verrou n'apparaisse pas dans pg_lock est logique du point de vue des performances. Car dans le scénario où une transaction met à jour des millions de ligne, on n'a pas tellement envie de maintenir une pseudo-table de millions de verrous juste pour avoir cette information qui dans le cas général n'est pas utile au client SQL normal.

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

Discussions similaires

  1. Trouver qui lock un enregistrement (pas bloque)
    Par schnourf dans le forum Oracle
    Réponses: 9
    Dernier message: 28/09/2019, 18h49
  2. Réponses: 1
    Dernier message: 22/12/2009, 09h23
  3. Réponses: 2
    Dernier message: 21/05/2002, 10h25
  4. Réponses: 4
    Dernier message: 27/03/2002, 11h03

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