Gestion de la concurrence d'accès dans une appli web jsp - Java - Programmation
Marsh Posté le 03-02-2004 à 19:52:50
C'est un pb qu'on peut régler en faisant ce qu'on appelle un "optimistic check".
Au moment de mettre à jour tes données, donc dans ton ordre "update", tu vérifies que les données qui sont actuellement présentes en base sont celles que tu as utilisées dans ta page.
Concrètement, tu définis une ou plusieurs colonnes de ta (tes) tables pour lesquelles tu ajoutes un critère dans ta clause where d'update (par ex un Timestamp de dernière mise à jour).
Ex :
Code :
|
Lorsque tu feras ton statement.executeUpdate(), tu auras en retour 0 (zéro) ou 1 lignes mises à jour. Si c'est zéro, ben ça veut dire que quelqu'un "d'autre" a fait une mise à jour entre temps. A toi de gérer ça dans ta JSP pour afficher le message adéquat à l'utilisateur.
Enjoy
Marsh Posté le 03-02-2004 à 20:27:33
une transaction JTA fera ça pour toi automatiquement. Voir si ton serveur le supporte
Marsh Posté le 03-02-2004 à 20:31:00
et une "bete" transaction jdbc suffirait pas?
Marsh Posté le 03-02-2004 à 20:34:27
the real moins moins a écrit : et une "bete" transaction jdbc suffirait pas? |
bin non y a pas d'isolation entre différents clients
Marsh Posté le 03-02-2004 à 20:40:44
je dis rien sur le coté technique, mais sur le principe, le dernier qui entre des données est censés avoir les données les plus fraiches... pourquoi empecher cet ecrasement (qui aura lieu dès que le premier utilisateur aura fait l'equivalent du commit)
Marsh Posté le 03-02-2004 à 20:45:20
DarkLord a écrit : |
je pensais que la transaction qu'on peut commiter/rollbacker sur java.sql.Connection etait basée sur cette Connection, donc si on part du principe qu'un objet Connection ne sera pas partagé (du moins pas tant que la tx n'a pas été commitée), c'est quoi le pb
Marsh Posté le 03-02-2004 à 20:49:17
Merci pour toutes vos réponses !
La solution de Ygrec me semble facile à mettre en oeuvre et semble répondre à mon problème. Encore merci !
Pour une transaction JTA, est-ce que quelqu'un aurait un exemple tout bête ?
Pour répondre à Uriel, admettons que A et B remplissent le champ commentaire du formulaire, il ne faut pas que celui de B écrase le commentaire de A. Dans le cas où on bloque la mise à jour de B, celui-ci verra ensuite le commentaire de A et viendra compléter mais en aucun cas ne l'écrasera.
Marsh Posté le 03-02-2004 à 20:52:14
Pour real moins moins : comment tu bloques l'accès à la fiche client quand un utilisateur est déjà en train de le modifier avec commit/rollback ?
Marsh Posté le 03-02-2004 à 20:52:45
the real moins moins a écrit : je pensais que la transaction qu'on peut commiter/rollbacker sur java.sql.Connection etait basée sur cette Connection, donc si on part du principe qu'un objet Connection ne sera pas partagé (du moins pas tant que la tx n'a pas été commitée), c'est quoi le pb |
oui mais il n'y a pas de lock sur la resource. Ce qui va se passer c'est que A va prendre le lock sur le client faire ses trucs et comitter. A ce moment B aura la possibilité de prendre le lock et de comitter d'autres modifs.
mais donc dans le cas web faut rafraichir les infos que A a comitté et ca c'est pas évident
Marsh Posté le 03-02-2004 à 20:54:17
fbarre a écrit : Pour real moins moins : comment tu bloques l'accès à la fiche client quand un utilisateur est déjà en train de le modifier avec commit/rollback ? |
je sais pas
Marsh Posté le 03-02-2004 à 20:55:45
DarkLord a écrit : |
j'ai tjs pas tout pigé.
(et qd tu parles de lock sur la resource, tu parles de? locker l'acces au "formulaire" par exemple? comment tu fais ça avec jta? )
Marsh Posté le 03-02-2004 à 20:56:05
fbarre a écrit : |
merci
Marsh Posté le 03-02-2004 à 21:02:54
the real moins moins a écrit : j'ai tjs pas tout pigé. |
non locker la resource qu'il veut accéder. Typiquement en JTA tu peux locket une instance d'un Entity Bean par exemple parce que tu as déclaré changer son état.
Dans JBoss avec la locking policy par défaut, tu lock tout ce que tu accèdes. Donc si tu démarres une transaction JTA et que tu fais un findByPrimaryKey sur un entity bean A, l'instance de A ne pourra pas etre modifiée par une autre transaction et son état est garantit consistent et durable à la fin de la transaction (commit) -> propriétés ACID de tout système transactionnel (Atomic, Consistent, Isolated, Durable)
Marsh Posté le 03-02-2004 à 21:15:34
tu peux locker quoi d'autre qu'un entity bean?
Marsh Posté le 03-02-2004 à 21:22:14
Si j'ai bien compris on peut utiliser une transaction JTA avec un Entity Bean. Seulement, je n'utilise pas d'entity bean, mais seulement des java beans standards (appli web simple : jsp/servlets/java beans). Mais merci pour ton aide DarkLord !
Marsh Posté le 03-02-2004 à 21:30:28
the real moins moins a écrit : tu peux locker quoi d'autre qu'un entity bean? |
tout ce qui peut etre enlisted dans une transaction JTA, i.e. qui implémente l'interface je-ne-sais-plus-comment qui définit ce qui faut faire en cas de commit/rollback pour la resource en question.
Bon w8 je me renseigne
Marsh Posté le 03-02-2004 à 21:32:39
fbarre a écrit : Si j'ai bien compris on peut utiliser une transaction JTA avec un Entity Bean. Seulement, je n'utilise pas d'entity bean, mais seulement des java beans standards (appli web simple : jsp/servlets/java beans). Mais merci pour ton aide DarkLord ! |
comme le dit moins moins, c'est possible via la connection (je ne savais pas). Mais donc dans ce cas c'est le SGBD qui doit fournir l'isolation
http://java.sun.com/j2ee/tutorial/ [...] tion9.html
Marsh Posté le 03-02-2004 à 21:44:16
ReplyMarsh Posté le 04-02-2004 à 18:03:56
On peut locker une ligne de table en faisant un "select for update" au lieu du select de base. Ensuite, si un autre client vient à essayer de lire la même ligne, il va rester bloqué jusqu'à ce que le verrou soit levé via commit ou rollback (sur la connection). C'est pour ça qu'il y a des SGBD (Oracle par ex) qui ont une option "nowait" : si le verrou ne peut pas être positionné sur ta ligne tu vas récupérer un code erreur de la BD et donc pouvoir avertir l'utilisateur avec un message du genre "cette donnée est en cours de modification par un autre utilisateur".
Maintenant au niveau web, si tu lockes les lignes au moment ou tu renvoies ta page à l'utilisateur, y'a comme un problème : quand est-ce que ce verrou est libéré, par ex si l'utilisateur ferme son browser ? Donc on ne verrouille pas les lignes au niveau du SGBD sauf en connaissance de cause, d'ou les histoires d'optimistic lock/check ...
Là le "message utilisateur" est un peu différent : c'est plutôt qque chose comme "les données que vous avez modifié ont été altérées par un autre utilisateur. Voulez-vous recharger les données actuelles ?"
Pour les histoires de lock sur les Entity il me semblait que c'était pareil, çàd que ton update va rester en "suspens" tant que l'autre transaction a pas commité/rollbacké. Tu ne sais pas à l'avance si y'a des modifications "pending", donc pas moyen d'avertir l'utilisateur ...
Ou me gourre-je (Darklord ?) ?
Marsh Posté le 04-02-2004 à 20:31:33
Bin oui et non, tout dépend de l'update. Mais donc en gros si un client1 choppe un record et le modifie; ca sera intègre et durable (dans le sens ou un client2 ne pourra pas chopper le meme record et le modifier pendant que client1 remplis le formulaire)
donc il y a bel et bien un lock. On peut le faire via le SGBD ou via un tx JTA
mais dans un cas comme dans l'autre, le message pour l'utilisateur va etre un peu hard à gerer
Marsh Posté le 04-02-2004 à 20:42:29
Ce que tu expliques c'est comment gérer l'intégrité des données. Ca c'est Ok.
Mais dans un contexte web, y'a un gros décalage entre le moment ou le user récupère les données et le moment où il les met à jour nan ? Donc pb potentiel "d'écrasement" comme en parle fbarre ...
Maintenant pour "avertir" un user qu'il va y avoir un pb de concurrence d'accès, à part les select for update (qu'il ne faut surtout pas faire n'importe comment je répète ) et les update avec une clause d'optimistic check, je connais pas d'autres méthodes ?
Marsh Posté le 04-02-2004 à 20:52:39
ET bien, je ne pensais pas que mon problème déchaînerait les foules :-)
Encore merci de vous décarcasser pour moi !
Marsh Posté le 04-02-2004 à 21:19:04
Ygrec a écrit : Ce que tu expliques c'est comment gérer l'intégrité des données. Ca c'est Ok. |
Merci de me prendre pour un kéké finit. Initialement je répondais à ca
Citation : |
et donc oui je sais que ca va pas par magie s'intégrer à un environnement web
Marsh Posté le 05-02-2004 à 20:47:31
Citation : |
Faut pas le prendre comme ça, je rajoutais juste de l'eau au moulin par rapport à la question initiale, that's all ...
Ok, la forme n'y était ptêt pas, sorry si ça t'a fait penser que je me moquais
Marsh Posté le 03-02-2004 à 19:11:39
Voilà mon problème :
J'ai une table dans ma base de données contenant les infos sur des clients, les nom et prénom, l'adresse, etc.
J'ai créé une page (formulaire) pour ajouter ou modifier un client dans la base. J'aimerais que deux utilisateurs ne puissent pas modifier un même client en même temps. Pour l'instant, comme il n'y a aucune vérification, seule la dernière modification est prise en compte. Si l'utilisateur B valide juste après l'utilisateur A, les modifications apportées par l'utilisateur A sont perdues. L'idéal serait qu'un message prévienne l'utilisateur B qu'un autre utilisateur (A) est déjà en train de modifier les infos du client.
Est-ce possible ?
Merci d'avance pour vos réponses.