Problème d'accès temps réel

Problème d'accès temps réel - SQL/NoSQL - Programmation

Marsh Posté le 18-01-2006 à 11:40:16    

Bonjour,
 
Je suis actuellement confronté à un problème d'accès simultanés dans ma base. La probabilité que celà arrive est relativement faible mais plutôt que d'avoir a mesurer les dégats, je préfère les éviter :whistle:.
 
J'ai une table "file_attente" dans laquelle chaque client va piocher une mission.
Lorsqu'un client prend une mission, il la marque avec son login. Elle est alors "reservée" et les autres clients n'y ont plus accès.
 
Mon soucis réside dans le fait que si deux clients interrogent la file en même temps, la réservation n'est posée par aucun des deux "à temps" et du coup il se passe le problème suivant.
 
Client A se voit attribuer mission 1.
Client B se voit attribuer mission 1.
Client A se réserve mission 1.
Client B se réserve mission 1 (et écrase la réservation A).
 
Est-il possible de temporiser la lecture de B tant que A n'a pas fini son opération de réservation afin de tomber dans le schéma suivant :
 
Client A se voit attribuer mission 1 et reserve la file en lecture.
Client B attend de pouvoir lire la file.
Client A se réserve mission 1 et libère la lecture de la file.
Client B se voit attribuer mission 2 car mission 1 reservée.
Client B réserve la file.
Client B se réserve mission 2 puis libère la lecture de la file.
 
J'ai trouvé un peu de doc sur les verrous mais je ne comprends pas comment les poser/retirer et sur quelles opérations ils portent.
 
Il faudrait donc que je puisse utiliser le principe du sémaphore pour contrôler l'accès à ma table "file_attente".
 
Merci :jap:

Reply

Marsh Posté le 18-01-2006 à 11:40:16   

Reply

Marsh Posté le 18-01-2006 à 11:52:31    

L'utilisation de transaction devrait régler ton problème


---------------
"I wonder if the internal negative pressure in self pumping toothpaste tubes is adjusted for different market altitudes." John Carmack
Reply

Marsh Posté le 18-01-2006 à 12:11:33    

Je viens de voir de la doc sur "select ... lock in share mode" et je me pose une question.
 
Si j'utilise cette syntaxe pour aller lire un enregistrement avec le client A et que le client B arrive avec un requête pour lire ce même enregistrment; que se passe-t-il ?
 
Le client B se fait jeter ? Il est mis en attente ?
 
Je jette un oeil aux transactions mais il faut déjà choisir entre 4 modes.
Le mode SERIALIZABLE n'est pas expliqué sur ma doc :/

Reply

Marsh Posté le 18-01-2006 à 13:29:36    

Je viens de coder quelque chose qui semble correct.
 
Dans mon appli client, j'encadre mes différentes requêtes par la commande "begin;" au début et "commit;" à la fin.
 
Parmi ces requêtes, la première est un select qui se termine par "for update" afin de bloquer les lectures simultanées.
 
Ca à l'air de tourner correctement.
 
Merci :)


Message édité par jeoff le 18-01-2006 à 13:30:25
Reply

Marsh Posté le 18-01-2006 à 14:32:35    

perso, je préfère largement l'utilisation d'un LOCK, car plus propre et plus explicite. normalement, t'as différent niveaux de LOCK, je te conseille d'utiliser celui "à la ligne" et "complet".
 
un lock nécessite d'être dans une transaction.
 
et c'est plus explicite (et plus propre) qu'un "for update".
 
et une instruction qui rencontre un LOCK attends patiemment la fin du lock jusqu'à expiration de son ticket (et plante si ça expire)

Reply

Marsh Posté le 18-01-2006 à 14:34:59    

seul truc important quand tu utilises un LOCK : fait gaffe aux DEAD LOCKS.
 
ca se produit quand t'as une procédure A et une procédure B.
 
La procédure A fait un lock sur la table T1
fait un select, update ou ce que tu veux dans T2
Unlock T1
 
La procédure B fait un lock sur la table T2
fait un select, update ou ce que tu veux dans T1
Unlock T2
 
Si tu lances T1 et T2 en même temps, t'as plus qu'à prendre un outils d'admin et shooter les deux connection, parceque si tu touches à rien, dans 10 ans les deux scrips seront toujours en train de s'attendre mutuellement.

Reply

Marsh Posté le 18-01-2006 à 15:41:47    

Je vais jeter un oeil par curiosité, merci ;)

Reply

Marsh Posté le 24-01-2006 à 16:37:04    

Je suis en train d'essayer les locks mais rien à faire, ca coince.
 
Est-il possible de locker une table en lecture/ecriture pour les autres threads sauf celui en cours ?
 
Parceque là je dois faire un select puis un update sur la même table mais :
- un lock read me bloque sur l'update,
- un lock write me bloque sur le select.
 
Je voudrais faire ça :
 

Code :
  1. connec->Send_Msg("LOCK TABLES file_palettisation WRITE, file_palettisation as file WRITE, bon_preparation WRITE, bon_preparation as bp WRITE;" );
  2. connec->Send_Msg("select file.no_bp,bp.lieu_stockage,bp.nb_colis_sur_zone from file_palettisation file,bon_preparation bp where file.no_bp='" + m_lst_file.GetItemText(m_lst_file.GetNextItem( -1, LVNI_FOCUSED ),3) + "' and (resa IS NULL or resa ='"+ connec->GetPortNum() +"') and file.no_bp=bp.no_bp order by bp.lieu_stockage asc;" );
  3. if (connec->recset[0][0]=="MySQL_no_result" )
  4. {
  5.  //lafin.domodal
  6.  MessageBox(_T("Cette mission vient d'être prise en charge. Choisissez en une autre !" ),_T("" ),MB_OK);
  7.  RefreshTable() ;
  8.  connec->Send_Msg("UNLOCK TABLES;" );
  9. }
  10. else
  11. {
  12.  connec->Send_Msg("update file_palettisation set resa='"+ connec->GetPortNum() +"' where no_bp='" + m_lst_file.GetItemText(m_lst_file.GetNextItem( -1, LVNI_FOCUSED ),3) + "';" );
  13.  connec->Send_Msg("UNLOCK TABLES;" );
  14.  Count.init(m_lst_file.GetItemText(m_lst_file.GetNextItem( -1, LVNI_FOCUSED ),3),m_lbl_moreinfo,connec);
  15.  Count.DoModal();
  16.  Onquitter();
  17. }


 
L'utilisateur doit choisir une mission dans une liste su son pocket PC.
Il y a plusieurs utilisateurs et 1 Pocket PC par utilisateur.
 
Pour s'assurer que deux utilisateurs A et B ne peuvent avoir la même mission, lorsque le choix de la mission est validé par A, je veux poser un vérou sur ma table 'file_palettisation'.
 
Je fais un select sur cette table :
 
CAS 1 : Si un utilisateur B a pris cette mission entretemps, le champs resa n'est plus null, un message averti l'utilisateur et le vérou est levé.
 
CAS 2 : Si cette mission est libre, le champs resa est null, je fais alors un update du champs resa pour signaler que la mission n'est plus disponible. Je lève alors le vérou.
 
 
EDIT : apparement le problème vient de ma passerelle. J'ai l'impression que je crée autant de thread que de requêtes différentes donc une instruction lock est executée dans un thread et le select dans un autre ... va falloir faire quelques modifs en profondeur  :sarcastic:


Message édité par jeoff le 25-01-2006 à 10:42:32
Reply

Marsh Posté le 25-01-2006 à 10:50:00    

Ok, j'ai résolu mon problème de passerelle, mes requêtes fonctionnent au poil, les accès sont verouillés au bon moment.
 
Seulement je me pose une question.
 
Mon schéma de fonctionnement : PocketPC <--WIFI--> Passerelle PC avec accès ODBC <--RJ45--> Serveur MySQL
 
Si je perds la connexion entre le PocketPC et la passerelle entre une instruction Lock et une instruction Unlock. Que se passe-t-il ?
La question est valable si la passerelle plante ou perds la connexion avec le serveur MySQL :D.
 
Est ce que MySQL possède des securités du type :
- si la connexion est fermée, les verrous sont relachés.  
- si une inactivité est detectée, les verrous sont relachés.
 
 
Merci :jap:


Message édité par jeoff le 25-01-2006 à 10:53:42
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed