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

JDBC Java Discussion :

Locker une ligne : SELECT FOR UPDATE


Sujet :

JDBC Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut Locker une ligne : SELECT FOR UPDATE
    Bonjour,

    Après deux jours de recherches je viens vers en espérant trouver ma réponse

    J'ai une application qui est utilisé en multi thread, et je veux qu'un thread puisse verrouiller une ligne (pour que les autres threads ne puisse rien faire sur cette ligne) pour là mettre à jour puis la débloquer après l'update.

    Donc je voulais utiliser SELECT FOR UPDATE, mais j'ai l'impression que ca ne fonctionne pas, voilà mon code :

    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public BasicJDBCDemo()
      {
        try
        {
        	conn = ds.getConnection();
        	conn.setAutoCommit(false);
        	doSelectTest();
        	doSelectTest();
     
            conn.close();
        }
        catch (SQLException ex)           
          {System.err.println(ex.getMessage());}
      }
     
      private void doSelectTest()
      {
        System.out.println("[OUTPUT FROM SELECT]");
        String query = "Select * from b2bicheckpoint where OID = ? FOR UPDATE";
        PreparedStatement pst = null;
        ResultSet rs=null;
        try
        {
          pst = conn.prepareStatement(query);
          pst.setLong(1, 3001);
          rs = pst.executeQuery();
     
          while (rs.next())
          {
            String s = rs.getString("HostName");
            long oid = rs.getLong("OID");
            System.out.println("OID/Host=="+oid+"/"+s);        
          }      
        }
        catch (SQLException ex)
        {
          ex.printStackTrace();
        }
        finally
        {
        	DBUtil.close(pst);
        	DBUtil.close(rs);
        }
      }
    Donc, le premier appel doSelectTest() devrait faire le lock, mais le deuxième appel doSelectTest() devrait planter en faisant le lock, ce qui n'est pas le cas, result :

    1) premier appel doSelectTest()

    [OUTPUT FROM SELECT]
    query==Select * from b2bicheckpoint where OID = ? FOR UPDATE
    OID/Host==3001/UnknownHost

    2) deuxiéme appel doSelectTest()

    [OUTPUT FROM SELECT]
    query==Select * from b2bicheckpoint where OID = ? FOR UPDATE
    OID/Host==3001/UnknownHost

  2. #2
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    La seule explication que je vois, c'est que le lock depend de la vie d'un ResultSet ou PreparedStatement .... Ca serait très dommage car dans une utilisation multi thread avec un pool de connection, chacun à ses propres connection, PreparedStatement , et resultSet!

    Merci de votre aide..........

  3. #3
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    Même en faisant un appel doSelectLock() (Select avec SELECT FOR UPDATE) puis doSelect() (Select simple), ca ne fonctionne pas, le deuxieme select me renvoi des info! :

    1) Premier appel
    [OUTPUT FROM SELECT Lock]
    query==Select * from b2bicheckpoint where OID = ? FOR UPDATE
    oid/host==3001/UnknownHost

    2) Deuxieme appel
    [OUTPUT FROM SELECT]
    query==Select * from b2bicheckpoint where OID = ?
    oid/host==3001/UnknownHost

    Pour info transaction-isolation = READ-COMMITTED dans mon SGBD, mais la colonne HostName est un index et d'après le manual MySQL avec READ-COMMITTED seul les index de la ligne seront locké, ce que je veux aussi. Mais ca ne fonctionne pas ai je oublié quelques choses ?

  4. #4
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    J'utilise MySQL innodb

  5. #5
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Ton test n'est pas le bon, là, tu utilises la même connexion donc le problème ne se pose pas.
    Essayer de faire un executable et de le lancer 2 fois ou alors, fais l'acquisition de 2 connexions pour faire le test.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    Merci OButterlin,

    Oki, maintenant j'ai crée une methode qui n'utilise pas de connection pool, et qui crée directement des nouvelle connections,

    code :
    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
     
    private static Connection getNewConnection()
    {
          System.out.println("New connection..");
          final String url = "url";
            Connection conn=null;
            try 
            {
                conn = DriverManager.getConnection(url, "user", "pwd");
            }
            catch (SQLException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
     
          return conn;
      }
    Puis dans voici mes fonctions :

    code :
    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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
     public BasicJDBCDemo()
      {
            //SELECT FOR UPDATE
            doSelectLockTest();
            //Simple SELECT
            doSelectTest();
     
      }
     
      private void doSelectLockTest()
      {
        System.out.println("[OUTPUT FROM SELECT Lock]");
        PreparedStatement pst = null;
        ResultSet rs=null;
        Connection conn=null;
     
        try
        {
          String query = "Select * from b2bicheckpoint where OID = ? FOR UPDATE";
            System.out.println("query=="+query);
     
           //new jdbc connection;
           conn=getNewConnection();
           conn.setAutoCommit(false);
           pst = conn.prepareStatement(query);
           pst.setLong(1, 3001);
           //Le run reste bloqué ici à cause du 'FOR UPDATE'!!!!
           rs = pst.executeQuery();
     
           while (rs.next())
           {
            String s = rs.getString("HostName");
            long oid = rs.getLong("OID");
            System.out.println("oid/host=="+oid+"/"+s);
          }      
        }
        catch (SQLException ex)
        {
          ex.printStackTrace();
        }
        finally
        {
            DBUtil.close(pst);
            DBUtil.close(rs);
            DBUtil.close(conn);
        }
      }
     
      private void doSelectTest()
      {
        System.out.println("[OUTPUT FROM SELECT]");
        String query = "Select * from b2bicheckpoint where OID = ?";
        System.out.println("query=="+query);
        PreparedStatement pst = null;
        ResultSet rs=null;
        Connection conn=null;
     
        try
        {
          conn=getNewConnection();          
          conn.setAutoCommit(false);
            pst = conn.prepareStatement(query);
        pst.setLong(1, 3001);
        rs = pst.executeQuery();
     
          while (rs.next())
          {
            String s = rs.getString("HostName");
            long oid = rs.getLong("OID");
            System.out.println("oid/host=="+oid+"/"+s);        
          }      
        }
        catch (SQLException ex)
        {
          ex.printStackTrace();
        }
        finally
        {
            DBUtil.close(pst);
            DBUtil.close(rs);
            DBUtil.close(conn);
        }
      }
    L'éxecution reste bloqué sur executeQuery() à cause du 'FOR UPDATE' est ce que c'est normal ? dois je exécuter deux thread pour le test??

    MErci

Discussions similaires

  1. select for update LOCK 3 10gR2
    Par petitfrere dans le forum Oracle
    Réponses: 1
    Dernier message: 01/12/2006, 18h52
  2. Select For Update Nowait
    Par e1lauren dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 28/09/2006, 22h04
  3. [FORMS PL/SQL] Select for Update
    Par taska dans le forum Forms
    Réponses: 3
    Dernier message: 30/08/2006, 10h33
  4. [MySql5]select ... for update
    Par melou dans le forum Requêtes
    Réponses: 1
    Dernier message: 20/04/2006, 11h11
  5. [Verrou] SELECT FOR UPDATE
    Par e1lauren dans le forum PostgreSQL
    Réponses: 10
    Dernier message: 13/10/2005, 17h06

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