简体   繁体   中英

Concurrent updates to oracle table in Java


I'm developing an application with some kind of 'facebook like' feature. Every time that a content published by a user is 'liked' he will have his punctuation increased. This app will be used by a large number of users around the company, so We are expecting a lot of concurrent updates to the same row.

simplified code

User punctuation table

Punctuation(
    userId NVARCHAR2(32),
    value NUMBER(10,0)
)/


Java code

public class Punctuation(){
    private String userId;
    private int value;

    public Punctuation(final String userId, final int value){
            this.userId = userId;
            this.value = value;
    }

    public String getUserId();
    public int getValue();

}

//simplified code
public final class PunctuationController{

    private PunctuationController(){}

    public static void addPunctuation(final Punctuation punctuation){

        final Transaction transaction = TransactionFactory.createTransaction();
        Connection conn = null;
        PreparedStatment statment = null;
        try{
                synchronized(punctuation){
                    transaction.begin();
                    conn = transaction.getConnection();
                    statment = conn.preparedStatment("UPDATE Punctuation SET value = value + ? where userId = ?");
                    statment.setString('1', punctuation.getUserId());
                    statment.setInt('2', punctuation.getValue());
                    transaction.commit();
                }
        }catch (Exception e){
                transaction.rollback();
        }finally{
                transaction.dispose();
                if(statment !=null){
                        statment.close();
                }
        }
}



We are afraid of deadlocks during updates. Oracle allows to make the sum on a single query, I don't have to retrieve the value and make a second query to update with a new value, that's good. Also reading some other posts here, They said to create a synchronized block to lock an object, and let Java handle the synchronization between different threads. I choose the punctuation instance the method receives, this way I imagine that different combinations of user and value will allow concurrent acess to this methods, but will block an instance with same values (Do I have to implement equals() on Punctuation?)

Our database is Oracle 10g, Server Weblogic 11g, Java 6 and Linux (I dont know which flavor).

Thank you in advance!

You're wrong on your synchronization strategy. synchronized uses the intrinsic lock of the object between parentheses. If you have two Punctuation instances that you might consider equal because they refer to the same user_id , Java doesn't care: 2 objects, so 2 locks, so no mutual exclusion.

I really don't see why the above, without the synchronized , could generate deadlocks: you're updating a single row in the table. You could have a deadlock if you had two concurrent transaction with one updating user1, then user2, and the other one updating user2, then user1. But even then, the database would detect the deadlock and throw an exception for one of the transactions.

you need to use optimistic lock pattern. take a look here for more details http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html

And probably this http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html which is more low level details

After identification of concurrent issue using optimistic lock, you may want to prefer re-trying - you have a full control what to do

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM