Alex Rivera | Logout

JDBC Lock a row using SELECT FOR UPDATE, doesn't work

Asked 2011-01-13T17:04:16.000
11

I am having issues with MySQL's SELECT .. FOR UPDATE, here is the query I am trying to run:

SELECT * FROM tableName WHERE HostName='UnknownHost' 
        ORDER BY UpdateTimestamp asc limit 1 FOR UPDATE

After this, the concerned thread will do an UPDATE and change the HostName, which is then it should unlock the row.

I am running a multi-threaded java application, so 3 threads are running this SQL statement, but when thread 1 runs this, it doesn't lock its results from thread 2 & 3. Therefore threads 2 & 3 are getting the same results and they could update the same row.

Also each thread is on its own mysql connection.

I'm using Innodb, with transaction-isolation = READ-COMMITTED, and the Autocommit is off before executing the select for update

may I miss something? OR perhaps there is a better solution? Thanks a lot.

Code :

public BasicJDBCDemo()
{
    Le_Thread newThread1=new Le_Thread();
    Le_Thread newThread2=new Le_Thread();
    newThread1.start();
    newThread2.start();         
}

Thread :

class Le_Thread extends Thread  
{

    public void run() 
    {
    tring name = Thread.currentThread().getName();
        System.out.println( name+": Debut.");
    long oid=Util.doSelectLockTest(name);
    Util.doUpdateTest(oid,name);        
    }

}

Select :

public  static long doSelectLockTest(String threadName)
  {
    System.out.println("[OUTPUT FROM SELECT Lock ]...threadName="+threadName);
    PreparedStatement pst = null;
    ResultSet rs=null;
    Connection conn=null;
    long oid=0;
    try
    {
     String query = "SELECT * FROM table WHERE Host=? 
                               ORDER BY Timestamp asc limit 1 FOR UPDATE";


      conn=getNewConnection();
      pst = conn.prepareStatement(query);
      pst.setString(1, DbProperties.UnknownHost);
      System.out.println("pst="+threadName+"__"+p
Edit
Report

1 Answer

1

The connection you create that selects for update needs to be the same one that is used to do the update. Otherwise it's not part of the same transaction and it releases the lock, so your other threads start to execute it as well. So in your code You need to do this:

if (rs.first())
  {
    String s = rs.getString("HostName");
    oid = rs.getLong("OID");
    System.out.println("oid_oldest/host/threadName=="+oid+"/"+s+"/"+threadName);

  }   
Util.doUpdateTest(oid,name,conn);
conn.commit();
answered 2011-01-13T17:24:24.017

Your Answer