Update / Select et Mysql

WRInaute accro
Bonjur à toutes et tous,

Un petit problème compliqué pour moi. Je vous explique.

J'ai une requete SELECT machinchose... elle s'affiche en 0,18. Ce SELECT est en fait une requête qui ne doit se calculer qu'une seule fois. Imaginez vous dans une file d'attente. Donc on ne la traite qu'une fois. Mais pdt ce laps de temps, 0,18, d'autres connectés ont pu lancer la meme requête... et donc je me retrouve avec deux personnes pour la même place dans la file d'attente. Génant. Surtout quand ils commencent à s'engueuler :)

Pour l'instant, après le SELECT et le 0,18, j'applique un UPDATE sur la table pour éviter le pb du "après le 0,18"... en effet, ensuite ca fait tourner une tite moulinette... genre on va le placer à la bonne table, on lui apporte le menu, etc... donc mon pb se retrouve donc limiter à ces 0,18

J'ai réfléchi sur le UPDATE SELECT... mais le pb c'est que j'ai besoin de récupérer des infos du SELECT, donc il me faudrait plutot un SELECT UPDATE

Alors si vous avez une tite idée, ce serait bien venue :)

Marchi
 
WRInaute accro
audit.referencement a dit:
J'avoue que je n'ai pas tout compris, tu n'as pas la possibilité de faire une vue avant ton select pour éviter le problème ?

en fait j'ai avancé... il faut que je verrouille la vue pdt que je la fais via un FOR UPDATE... seul soucis... mon MySql a pas l'air d'aimer le FOR UPDATE
 
WRInaute impliqué
j'ai bien peur qu'avec du mysql standard tu ne puisses rien faire, myIsam ne propose pas de verrou sur une ligne par contre si tu peux passer ta table en innodb tu as l'instruction select for update qui réalise exactement ce que tu veux faire c'est à dire verrouiller la donnée tant que l'update n'est pas passé...
+ d'infos ici
 
WRInaute accro
julienr a dit:
j'ai bien peur qu'avec du mysql standard tu ne puisses rien faire, myIsam ne propose pas de verrou sur une ligne par contre si tu peux passer ta table en innodb tu as l'instruction select for update qui réalise exactement ce que tu veux faire c'est à dire verrouiller la donnée tant que l'update n'est pas passé...
+ d'infos ici

Arf c bien ce que j'étais en train de capter. Oui la table est en MyISAM mais je peux la modifier en innodb. Y'a pas un risque dans ce genre de modif ?

pas tout compris. les transactions peuvent pas t'aider ?

Les trucs avec les lock ? je suis en train de regarder par là aussi
 
WRInaute accro
"Y'a pas un risque dans ce genre de modif"

Jamais testé de conversion par contre les sauvegardes doivent être faites proprement, les cc de fichiers ça ne marche plus trop notamment en cas de changement de version.

Certaines requêtes peuvent ralentir, aussi (WHERE), vu qu'il y a plus de contrôle dans InnoDB.
 
WRInaute impliqué
non pas grand risque à passer en innodb sauf qu'il faut savoir :
- il n'y a pas d'index fulltext en innodb
- les count(*) sont très lent si tu n'as pas de clause where dans la requete ...
 
WRInaute accro
bon je suis passé en innodb sur deux tables... oui en plus dans le select y'a une jointure lol ... et sans succès

A chaque fois j'ai un "#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ..."

le FOR UPDATE il se met après le LIMIT ? après le ORDER ? après toutes les clauses WHERE ? j'ai tout testé lol
 
WRInaute accro
Si c'est un système d'id de file d'attente, tu ne peux pas t'en sortir en faisant un id=id+1 dans ton update ou via un autoincrement et un lastinsertid ?

C'est peut-être très c** ce que je dis mais j'essaie de piger ton problème.
 
WRInaute accro
c pas con... c meme comme ca que je faisais avant... mais là le SELECT prend 0,18 ... et pdt ce laps de temps, d'autres personnes peuvent faire tourner le SELECT tant que j'ai pas fait le UPDATE
 
WRInaute impliqué
select for update s'applique qu' à une seule table
si tu as une jointure c'est à dire que tu veux vérouiller une table et updater dans une autre
il te faudra gérer explicitement les verrous
 
WRInaute accro
finstreet a dit:
c pas con... c meme comme ca que je faisais avant... mais là le SELECT prend 0,18 ... et pdt ce laps de temps, d'autres personnes peuvent faire tourner le SELECT tant que j'ai pas fait le UPDATE

Un collègue me parle aussi du générateur d'UID, qui te permet de générer le numéro de ticket en dehors du SQL et avec une probabilité limitée d'avoir deux id identiques.

EDIT-
C'est pê bien ça http://be.php.net/uniqid
 
WRInaute accro
julienr a dit:
select for update s'applique qu' à une seule table
si tu as une jointure c'est à dire que tu veux vérouiller une table et updater dans une autre
il te faudra gérer explicitement les verrous

ahhhhhhhhhh ben en fait je veux verrouiller le résultat de mon SELECT pas vraiment ma table ... et suis obligé de faire une jointure, c'est un SELECT assez complexe avec des IF en prime :)

Donc pour éviter la jointure, si je me souviens bien, il suffit de me créer une table temporeraire dans laquelle je taperais pour chercher les infos et là je pourrais la verrouiller celle là ... ah non ... je réflechis en meme temps... si elle est temporaire , elle s'appliquera pas à tous les visiteurs... et si elle est pas temporaire, ca risque d'etre aussi la meme m.... arf quel cirque
 
WRInaute accro
ecocentric a dit:
Un collègue me parle aussi du générateur d'UID, qui te permet de générer le numéro de ticket en dehors du SQL et avec une probabilité limitée d'avoir deux id identiques.

oui mais pour ce genre de trucs, il faut que je repense entièrement quelques tables... et là à la base j'aurais aimé un truc simple... je pense que j'aurais pas trop le choix que de ratravailler dessus :-( snif
 
WRInaute accro
finstreet a dit:
ecocentric a dit:
Un collègue me parle aussi du générateur d'UID, qui te permet de générer le numéro de ticket en dehors du SQL et avec une probabilité limitée d'avoir deux id identiques.

oui mais pour ce genre de trucs, il faut que je repense entièrement quelques tables... et là à la base j'aurais aimé un truc simple... je pense que j'aurais pas trop le choix que de ratravailler dessus :-( snif

Sorry, j'essaie de brainstormer un max, après à toi de voir :D
 
WRInaute accro
j'ai bidouillé un truc ... ca devrait résoudre une partie des pbs ... pour le moment ca sera suffisant. Je m'y remettrais plus tard :)
 
WRInaute discret
Je te propose :

1.) Test d'un indicateur dans une table SQL "technique" ou dans un fichier

2.)
Si OK :
Mise à KO de cet indicateur
Execution de ton SELECT de 0,18 s
Execution de ton UPDATE
Mise à OK de cet indicateur

Si KO :
Execution d'un temps d'attente (wait en php)
Relance à l'étape 1.)
 
WRInaute accro
Selection A a dit:
test d'une simple variable booléenne (oui ou non) stockée dans un fichier ou une table SQL

ah... oui là je vois un peux mieux ... ca diminue le risque d'avoir deux personnes en meme temps sur la meme requete, mais ca le supprime pas
 
WRInaute accro
finstreet a dit:
Selection A a dit:
test d'une simple variable booléenne (oui ou non) stockée dans un fichier ou une table SQL

ah... oui là je vois un peux mieux ... ca diminue le risque d'avoir deux personnes en meme temps sur la meme requete, mais ca le supprime pas

En gros, si je suis bien, ça revient à implémenter une sorte de métaphore ^^.

Ce que je verrais pour résoudre le problème:

Code:
Faire
{
  Mettre le verrou à bloqué si verrou libre et affecter un UID (UPDATE).
  Vérifier la réservation (par existance UID). 
  Si réservé, condition d'arrêt à Vrai. 
  Si échec de la réservation, condition d'arrêt à FAUX et temporisation de 0,1s
}
Tant que pas condition d'arrêt vérifiée.

Faire le traitement (gros SELECT + UPDATE).
Débloquer le verrou.
 
WRInaute discret
Moi j'aurais vu ça plus comme ça
J'apelle fic.inc le fichier contenant l'indicateur $indic (1 pour non reservé ou 0 pour réservé)

Code:
// compteur permettant d'éviter de boucler plus de 5 fois
$compteur = 1;
Lecture fic.inc
Tant que $indic = 0 ET $compteur < 6 
  {
  Temporisation
  Lecture fic.inc
  $compteur = $compteur + 1;
  }
Si $indic == 1
  {
  $indic = 0
  Ecriture fic.inc
  requete SELECT
  requete UPDATE
  $indic = 1
  Ecriture fic.inc
  }
Si indic == 0
  {
   Traitement erreur
  }
 
WRInaute accro
J'éviterais les écritures dans des fichiers pour des raisons d'accès concurrentiel, d'autant que je me souviens avoir lu que les lock de fichiers n'étaient pas fiables. Bref, je préfère me rabattre sur le SGBD pour gérer les accès concurrents en UPDATE.
 
WRInaute discret
Pour moi il y a pas d'histoire de lock et de délock sur le fichier.

L'algo que j'ai proposé n'est peut etre pas le plus optimum mais je pense qu'il réduit considérablement les riques. Le temps critique est entre la lecture et l'ecriture mais c'est juste quelques centièmes de secondes et donc bien mois que 0.15s
 
WRInaute accro
finstreet a dit:
ah je comprends mieux... mais le fichier lock et pas lock... à quel moment on le lock et on le délocke ?
Je disais ça parce que tu peux avoir des écritures simultanées sur le fichier. Faut voir si c'est grave, pas vraiment regardé. Juste que le SGBD gère a priori la concurrence, ce qui me rend plus confiant dans une solution basée sur MySQL que sur des fichiers.
 
WRInaute accro
ben en fait, j'ai nettement réduit le pb... et je pense encore le réduire en rajoutant un truc avant le select, comme dit plus haut

Si c'est 0, alors on fait transforme en 1, et on fait le select, et on mouline et ensuite on remet à 0

Le update entre le 0 et le 1 est ridicule en temps
 
WRInaute accro
finstreet a dit:
ben en fait, j'ai nettement réduit le pb... et je pense encore le réduire en rajoutant un truc avant le select, comme dit plus haut

Si c'est 0, alors on fait transforme en 1, et on fait le select, et on mouline et ensuite on remet à 0

Le update entre le 0 et le 1 est ridicule en temps

Oui, ça rejoint mon idée de verrou plus haut, alors ^^
 
Discussions similaires
Haut