Actualizaciones simultáneas de la tabla Oracle en Java


Estoy desarrollando una aplicación con algún tipo de función de 'Me gusta de Facebook'. Cada vez que un contenido publicado por un usuario sea 'me gusta' verá aumentada su puntuación. Esta aplicación será utilizada por una gran cantidad de usuarios de la empresa, por lo que esperamos muchas actualizaciones simultáneas en la misma fila.

código simplificado

Tabla de puntuación del usuario

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


Código Java

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();
                }
        }
}



Tenemos miedo de los puntos muertos durante las actualizaciones. Oracle permite hacer la suma en una sola consulta, no tengo que recuperar el valor y hacer una segunda consulta para actualizar con un nuevo valor, eso es bueno. También leyendo algunas otras publicaciones aquí, dijeron que crearan un bloque sincronizado para bloquear un objeto y dejar que Java maneje la sincronización entre diferentes subprocesos. Elijo la instancia de puntuación que recibe el método, de esta manera imagino que diferentes combinaciones de usuario y valor permitirán el acceso simultáneo a estos métodos, pero bloquearán una instancia con los mismos valores (¿Tengo que implementar equals() en Punctuation?)

Nuestra base de datos es Oracle 10g, Server Weblogic 11g, Java 6 y Linux (no sé de qué sabor).

Gracias de antemano!

preguntado el 31 de julio de 12 a las 11:07

2 Respuestas

Te equivocas en tu estrategia de sincronización. synchronized utiliza el bloqueo intrínseco del objeto entre paréntesis. si tienes dos Punctuation instancias que podría considerar iguales porque se refieren a lo mismo user_id, a Java no le importa: 2 objetos, por lo que 2 bloqueos, por lo que no hay exclusión mutua.

Realmente no veo por qué lo anterior, sin el synchronized, podría generar interbloqueos: está actualizando una sola fila en la tabla. Podría tener un interbloqueo si tuviera dos transacciones simultáneas con una actualización de usuario1, luego usuario2, y la otra actualización de usuario2, luego usuario1. Pero incluso entonces, la base de datos detectaría el interbloqueo y generaría una excepción para una de las transacciones.

Respondido 31 Jul 12, 11:07

¡Gracias! eso era algo que me preocupaba, que mi estrategia sincronizada estuviera equivocada. - artureld

necesita usar un patrón de bloqueo optimista. echa un vistazo aquí para más detalles http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html

Y probablemente esto http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/The_CMP_Engine-Optimistic_Locking.html que es más detalles de bajo nivel

Después de identificar el problema concurrente mediante el bloqueo optimista, es posible que prefiera volver a intentarlo: tiene un control total de lo que debe hacer

Respondido 31 Jul 12, 11:07

Dado que la base de datos realiza la adición, aquí no es necesario el bloqueo optimista. - JB Nizet

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.