2014-06-14 4 views
0

J'ai une application concurrente qui doit mettre à jour l'incrémenté/décrémenté (changement d'équilibre) dans la colonne solde de la table des comptes. J'utilise Oracle Toplink. Une façon d'effectuer les mises à jour simultanées consiste à utiliser le verrouillage optimiste à l'aide de la colonne version.Oracle Toplink: montant d'incrémentation/décrémentation atomique

1) Optimiste verrouillage

mise à jour de la balance set account = ?, version =? où id =? et version =?

2) mise à jour atomique

mise à jour de la balance set compte = solde +? où id =?

Je voudrais utiliser l'option 2) car c'est plus facile et ne nécessite pas que je lise la valeur avant la mise à jour (comme dans 1)).

SQLCall sc = new SQLCall("update account set balance=balance + #delta where id=#id"); 
DataModifyQuery data = new DataModifyQuery(sc); 
data.addArgument("delta", BigDecimal.class); 
data.addArgument("id", Long.class); 
Vector param = new Vector(2); 
param.add(new BigDecimal(.01)); 
param.add(new Long(12345)); 
getSession().executeQuery(data, param); 

Je rencontre un problème lors de l'exécution de la requête de mise à jour. Le problème est que cela ne reflète pas le montant à la fin.

est 2) l'option est vraiment mise à jour atomiquement? Ai-je suivi la bonne approche de codage? Quelque chose ne va pas avec cet exemple?

S'il vous plaît guider

Répondre

0

Votre mise à jour atomique est pas atomique.

Si plusieurs transactions le font simultanément, les deux vont incrémenter leur propre vue du solde actuel, et le dernier va gagner. En effet, les transactions sont isolées les unes des autres (c'est le I dans ACID), et ne voient pas les modifications apportées par d'autres transactions.

Vous avez toujours besoin d'un verrouillage (optimiste ou pessimiste) pour le faire correctement.

+0

merci pour la réponse rapide. que diriez-vous d'ajouter "BEGIN" et "END" autour de la requête? Verrouillera-t-il la rangée? –

+0

Oracle ne se gère-t-il pas? Je veux dire pourquoi l'application doit garder une vue de l'équilibre actuel. La requête ci-dessous indique, 'ajoutez juste delta à la valeur existante' et l'application ne se soucie pas de l'ordre de l'addition de valeurs delta par différents threads. > Mettre à jour le solde du compte = solde +? où id =? J'avais essayé cette approche en utilisant jdbc et cela a fonctionné. Y a-t-il une différence entre utiliser jdbc et toplink dans ce cas? –

+0

va changer executeQuery() pour exécuterNonSelectingCall() faire la différence? –