Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[HS] Equivalent des locks en sql

15 réponses
Avatar
patrice
Bonjour

Y'a eu un thread récent sur les locks de mysql.
D'apres ce que j'ai lu, il semblerait qu'il faille éviter de les utiliser.

Autant pour mettre a jour une fiche, "le dernier qui parle a raison" me
semble une bonne méthode.
Mais comment se gere par exemple la vente de produit en stock.

En hf (séquentiel indexé) standard, on ferait un truc du genre :
verouille(fiche_produit)
si qte_dispo>=quantité_demandé alors qte_dispo=qte_dispo -
quantité_demandé, enregistrer(fiche_produit)
sinon
deverouille(fiche_produit)
afficher "Cette quantité n'est pas disponible"

Cela permet d'etre sur de ne vendre que ce que l'on a.
Mais que devient cet algorithme en sql, mysql, mssql ? existe une facon
standard de procéder ?

10 réponses

1 2
Avatar
Gilles
Il se trouve que patrice a formulé :
Bonjour

Y'a eu un thread récent sur les locks de mysql.
D'apres ce que j'ai lu, il semblerait qu'il faille éviter de les utiliser.

Autant pour mettre a jour une fiche, "le dernier qui parle a raison" me
semble une bonne méthode.
Mais comment se gere par exemple la vente de produit en stock.

En hf (séquentiel indexé) standard, on ferait un truc du genre :
verouille(fiche_produit)
si qte_dispo>=quantité_demandé alors qte_dispo=qte_dispo -
quantité_demandé, enregistrer(fiche_produit)
sinon
deverouille(fiche_produit)
afficher "Cette quantité n'est pas disponible"

Cela permet d'etre sur de ne vendre que ce que l'on a.



Ca dépend de ce que tu as à vendre.
Mais le plus efficace reste de réserver l'item sélectionner et de le
considérer hors stock jusqu'à validation ou annulation de la commande.

avec bien sûr le cas à gérer du plantage. (il faut donc gérer ces
quantités réservées avec des timestamps)
Avatar
patrice
"Gilles" a écrit dans le message de
news:
Ca dépend de ce que tu as à vendre.
Mais le plus efficace reste de réserver l'item sélectionner et de le
considérer hors stock jusqu'à validation ou annulation de la commande.

avec bien sûr le cas à gérer du plantage. (il faut donc gérer ces
quantités réservées avec des timestamps)




Je vois pas comment effectuer cette réservation .

Si on vend des produits unitaires (une fiche par produit à vendre), il y
aurait un flag "reservé", mais comment garantir de ne positionner ce flag
que s'il n'est pas déjà positionné.
(2 personne liste la table, l'item n'est pas réservé, les 2 le réserve en
même temps)

Si on vend des produits en quantité (une fiche par produit, avec champ
quantité), comment soustraire une quantité que si la quantité est supérieure
à la quantité à soustraire (on parle bien sur de 2 personnes faisant la
requete en meme temps)
Avatar
Gilles
patrice vient de nous annoncer :
"Gilles" a écrit dans le message de
news:
Ca dépend de ce que tu as à vendre.
Mais le plus efficace reste de réserver l'item sélectionner et de le
considérer hors stock jusqu'à validation ou annulation de la commande.

avec bien sûr le cas à gérer du plantage. (il faut donc gérer ces
quantités réservées avec des timestamps)




Je vois pas comment effectuer cette réservation .

Si on vend des produits unitaires (une fiche par produit à vendre), il y
aurait un flag "reservé", mais comment garantir de ne positionner ce flag
que s'il n'est pas déjà positionné.
(2 personne liste la table, l'item n'est pas réservé, les 2 le réserve en
même temps)

Si on vend des produits en quantité (une fiche par produit, avec champ
quantité), comment soustraire une quantité que si la quantité est supérieure
à la quantité à soustraire (on parle bien sur de 2 personnes faisant la
requete en meme temps)



Tu fais une table de réservations (qui contient, id incrémental, id
produit, et quantité, et éventuellement dateheure pour les crashs)

quand tu ajoutes un produit en stock, tu ajoutes la ligne
correspondante et tu gardes l'id d'insertion en mémoire.

Quand tu valides, après le destockage réel, tu supprimes cette ligne.

tu ne peux jamais te retrouver en défaut, seulement en excès.

pour le cas peu probable où une autre lecture s'est faite entre ta
lecture et ton insert de réservation, tu revérifies les quantités en
stock et en réservation au moment de l'enregistrement réel de la
commande.
Avatar
Daniel
patrice a écrit :
"Gilles" a écrit dans le message de
news:
Ca dépend de ce que tu as à vendre.
Mais le plus efficace reste de réserver l'item sélectionner et de le
considérer hors stock jusqu'à validation ou annulation de la commande.

avec bien sûr le cas à gérer du plantage. (il faut donc gérer ces
quantités réservées avec des timestamps)




Je vois pas comment effectuer cette réservation .

Si on vend des produits unitaires (une fiche par produit à vendre), il y
aurait un flag "reservé", mais comment garantir de ne positionner ce flag
que s'il n'est pas déjà positionné.
(2 personne liste la table, l'item n'est pas réservé, les 2 le réserve en
même temps)

Si on vend des produits en quantité (une fiche par produit, avec champ
quantité), comment soustraire une quantité que si la quantité est supérieure
à la quantité à soustraire (on parle bien sur de 2 personnes faisant la
requete en meme temps)





faire un select for update pour récupérer la valeur du stock et ensuite
un update, le tout dans une transaction.



--
suivre ce lien pour répondre:
http://cerbermail.com/?2KrV3YZXnn
Daniel
;-)
Avatar
patrice
Merci daniel
en regardant dans la doc le select for update je tombe sur :
Dans ce cas, il y a deux bonnes méthodes pour implémenter la lecture et
l'incrémentation du compteur : (1) modifiez le compteur d'une unité, et
lisez le après cela ou (2) lisez le compteur d'abord, avec un verrou en mode
FOR UPDATE, puis incrémentez le :

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;
c'est exactement ca.merci

"Daniel" a écrit dans le message de
news:49ca678f$0$3511$
patrice a écrit :
> "Gilles" a écrit dans le message de
> news:
>> Ca dépend de ce que tu as à vendre.
>> Mais le plus efficace reste de réserver l'item sélectionner et de le
>> considérer hors stock jusqu'à validation ou annulation de la commande.
>>
>> avec bien sûr le cas à gérer du plantage. (il faut donc gérer ces
>> quantités réservées avec des timestamps)
>>
>
> Je vois pas comment effectuer cette réservation .
>
> Si on vend des produits unitaires (une fiche par produit à vendre), il y
> aurait un flag "reservé", mais comment garantir de ne positionner ce


flag
> que s'il n'est pas déjà positionné.
> (2 personne liste la table, l'item n'est pas réservé, les 2 le réserve


en
> même temps)
>
> Si on vend des produits en quantité (une fiche par produit, avec champ
> quantité), comment soustraire une quantité que si la quantité est


supérieure
> à la quantité à soustraire (on parle bien sur de 2 personnes faisant la
> requete en meme temps)
>
>

faire un select for update pour récupérer la valeur du stock et ensuite
un update, le tout dans une transaction.



--
suivre ce lien pour répondre:
http://cerbermail.com/?2KrV3YZXnn
Daniel
;-)


Avatar
Gilles
Il se trouve que patrice a formulé :
Merci daniel
en regardant dans la doc le select for update je tombe sur :
Dans ce cas, il y a deux bonnes méthodes pour implémenter la lecture et
l'incrémentation du compteur : (1) modifiez le compteur d'une unité, et
lisez le après cela ou (2) lisez le compteur d'abord, avec un verrou en mode
FOR UPDATE, puis incrémentez le :

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;
c'est exactement ca.merci



Tu ne voulais pas un truc "standard"?
Parce que Select for update n'existe pas sur toutes les bases (à
commencer par MS SQL Server)

Gilles.
Avatar
Daniel
Gilles a écrit :
Il se trouve que patrice a formulé :
Merci daniel
en regardant dans la doc le select for update je tombe sur :
Dans ce cas, il y a deux bonnes méthodes pour implémenter la lecture et
l'incrémentation du compteur : (1) modifiez le compteur d'une unité, et
lisez le après cela ou (2) lisez le compteur d'abord, avec un verrou
en mode
FOR UPDATE, puis incrémentez le :

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;
c'est exactement ca.merci



Tu ne voulais pas un truc "standard"?
Parce que Select for update n'existe pas sur toutes les bases (à
commencer par MS SQL Server)

Gilles.





Sinon voir http://sqlpro.developpez.com/cours/sqlaz/techniques/#L1 qui
doone plein d'info sur le niveau de transaction à utiliser.


--
suivre ce lien pour répondre:
http://cerbermail.com/?2KrV3YZXnn
Daniel
;-)
Avatar
Firetox
Bonjour,

Tu ne voulais pas un truc "standard"?
Parce que Select for update n'existe pas sur toutes les bases (à commencer
par MS SQL Server)



si et SQLServer va plus loin
sur mySQL quand une ligne est locké par un select for update les select
suivat seront bloqué jusqu' aliberation de la transaction

sous SQLserver on peut choisir lorsqu'on lock une ligne de bloquer les
select ou les update concurrents
c'est a dire je lock une ligne en specifiant que tout select sera bloqué
ou alors je bloque la ligne et je demande que seul les update seront bloque
ce qui a pour effet de laisser les select concurrent passés mais si un
update est envoyé alors que je bloque la ligne il sera refusé avec le
message que la ligne est bloque

mais dans tous les cas c'est quand je fais le select (comme un select for
update) que je le specifie

Bon dev
@+
Avatar
Gilles
Dans son message précédent, Firetox a écrit :
Bonjour,

Tu ne voulais pas un truc "standard"?
Parce que Select for update n'existe pas sur toutes les bases (à commencer
par MS SQL Server)





si et SQLServer va plus loin
sur mySQL quand une ligne est locké par un select for update les select
suivat seront bloqué jusqu' aliberation de la transaction



En SQL 2005?
On n'a pas réussi à avoir le comportement adéquat en SQL 2000, et on
avait abandonné l'idée. Si ca marche en 2000, je reverrais mes procs
immédiatement, tu as un sample?
Avatar
Firetox
Bonjour,

En SQL 2005?
On n'a pas réussi à avoir le comportement adéquat en SQL 2000, et on avait
abandonné l'idée. Si ca marche en 2000, je reverrais mes procs
immédiatement, tu as un sample?



en SQL 2005 et 2008 sur en 2000 je n'ai pas de version pour faire le tests
mais mes souvenirs me disent que cela fonctionne

Lock au select
SELECT................... WITH(UPDLOCK, HOLDLOCK, ROWLOCK) WHERE
A Execute cette requete
Si B exexcute cette requete ==> ligne bloque jusqu'a ce que A libere la
transaction

Lock a l'update :
SELECT.....................WITH(HOLDLOCK, ROWLOCK) WHERE ..............
A execute cette requete
B execute cette requete : il obtient la ligne
B fait Update sur la ligne ====> ligne bloquée jusqu'a ce que A libere la
transaction

le tout dans une transaction

j'utilise le premier pour locker au niveau select comme sous mySQL
dans le projet exemple mssql4wd il y a deux boutons qui font ca. en lacant 2
exe on peut jouer avec et voir le comportement.

Bon dev
@+
1 2