PSP, Base de données et accès concurent

PSP, Base de données et accès concurent - Python - Programmation

Marsh Posté le 06-07-2009 à 13:04:19    

Bonjour,
J'ai un peu l'habitude de faire des scripts pythons en mode texte pour faire des modifs en base de données, et là, je dois faire un petit site en PSP.
Pour l'instant, j'ai fait des pages qui contienne un import :  
from configdb import *
 
Et un fichier configdb.py qui contient ça :
 

Code :
  1. try:
  2.    connectionMy = MySQLdb.connect(host = "XXX", user = "YYY", passwd = "ZZZ", db = "AAA",use_unicode=1)
  3. except OperationalError:
  4.    req.write("Unable to connect to database: %s" % message)


 
Mais j'ai l'impression que la "connection" est parfois perdu et je ne comprends pas très bien comment les choses fonctionnent quand deux personnes se connectent en même temps ?  
Est ce qu'il y a un seul objet connectionMy qui est utilisé par les deux personnes ? est ce qu'il y a un nouvel objet connectionMy à chaque fois que quelqu'un accède à la page ?
 
Bref, ne comprenant pas trop comment ça fonctionne, j'ai du mal à savoir comment je pourrais corriger les choses.
 
Merci pour votre aide,
 
Axel

Reply

Marsh Posté le 06-07-2009 à 13:04:19   

Reply

Marsh Posté le 13-08-2009 à 21:04:00    

axel584 a écrit :

Bonjour,
J'ai un peu l'habitude de faire des scripts pythons en mode texte pour faire des modifs en base de données, et là, je dois faire un petit site en PSP.
Pour l'instant, j'ai fait des pages qui contienne un import :  
from configdb import *
 
Et un fichier configdb.py qui contient ça :
 

Code :
  1. try:
  2.    connectionMy = MySQLdb.connect(host = "XXX", user = "YYY", passwd = "ZZZ", db = "AAA",use_unicode=1)
  3. except OperationalError:
  4.    req.write("Unable to connect to database: %s" % message)


 
Mais j'ai l'impression que la "connection" est parfois perdu et je ne comprends pas très bien comment les choses fonctionnent quand deux personnes se connectent en même temps ?  
Est ce qu'il y a un seul objet connectionMy qui est utilisé par les deux personnes ? est ce qu'il y a un nouvel objet connectionMy à chaque fois que quelqu'un accède à la page ?
 
Bref, ne comprenant pas trop comment ça fonctionne, j'ai du mal à savoir comment je pourrais corriger les choses.
 
Merci pour votre aide,
 
Axel


 
C'est plus une question spécifique aux bdd qu'à Python. Chaque connection à une bdd est gérée par le serveur. Il attribue au client un identificateur de connection.
Ensuite, quand le serveur reçoit une requête, il sait de qui ça vient grâce à l'identificateur qui est associé.
 
Le vrai problème peut survenir si les deux clients modifient la même info d'une même table en même temps. Si la modif est faite de façon banale, alors le serveur recevant les deux requêtes les exécutera en séquentiel et c'est la dernière qui gagnera.
Généralement, pour éviter ce genre de cas, on pose un verrou sur l'enregistrement en cours de traitement. Le verrou peut-être en mode "lecture seule" (les autres peuvent toujours lire l'info mais pas la modifier) ou en mode "exclusif".
 
Pour en revenir à Python, j'ai découvert un problème justement à propos de l'info visualisée.
 
Voici 2 scripts
script1.py: il crée une bdd et une table et il y stocke 3 infos. Puis il va lire les infos, attend ensuite une frappe clavier puis relit les infos

Code :
  1. #!/usr/bin/env python
  2. # coding: Latin-1 -*-
  3. # Programme principal
  4.  
  5. # Paramètres de travail
  6. __serveur="localhost"
  7. __user="mysql"
  8. __passwd="mot de passe de mySQL"
  9. __bdd="toto"
  10. __table="tbl"
  11.  
  12. import MySQLdb
  13.  
  14. # Partie 1: Création bdd
  15. id=MySQLdb.connect(__serveur, __user, __passwd)
  16.  
  17. c=id.cursor()
  18. c.execute("drop database if exists %s" % __bdd)
  19. c.execute("create database %s" % __bdd)
  20. c.close()
  21. id.close()
  22.  
  23. # Partie 2: Création et remplissage table
  24. id=MySQLdb.connect(__serveur, __user, __passwd, __bdd)
  25. c=id.cursor()
  26. c.execute("create table %s (nom char(20), prenom char(20))" % __table)
  27. c.close()
  28.  
  29. c=id.cursor()
  30. c.execute("insert into %s (nom, prenom) values('Valjean', 'Jean')" % __table)
  31. c.execute("insert into %s (nom, prenom) values('Hugo', 'Victor')" % __table)
  32. c.execute("insert into %s (nom, prenom) values('Javert', 'Paul')" % __table)
  33. c.close()
  34. id.commit()
  35. id.close()
  36.  
  37. # Partie 3: Affichage n° 1
  38. print
  39. print "Affichage 1"
  40. id=MySQLdb.connect(__serveur, __user, __passwd, __bdd)
  41. c=id.cursor()
  42. c.execute("select * from %s order by nom" % __table)
  43. print c.fetchall()
  44. print "%d lignes\n" % c.rowcount
  45. c.close()
  46.  
  47. # Partie 4: Attente
  48. print
  49. raw_input("Attente - Permet de lancer autre chose - Appuyer sur <return> pour continuer" )
  50.  
  51. # Partie 5: Affichage n° 2
  52. print
  53. print "Affichage 2"
  54. c=id.cursor()
  55. c.execute("select * from %s order by nom" % __table)
  56. print c.fetchall()
  57. print "%d lignes\n" % c.rowcount
  58. c.close()
  59. id.close()


 
script2.py: il se connecte à la bdd et y insère des data

Code :
  1. #!/usr/bin/env python
  2. # coding: Latin-1 -*-
  3. # Programme principal
  4.  
  5. # Paramètres de travail
  6. __serveur="localhost"
  7. __user="mysql"
  8. __passwd="mot de passe de mySQL"
  9. __bdd="toto"
  10. __table="tbl"
  11.  
  12. import MySQLdb
  13.  
  14. # Partie 1: Insertion dans table
  15. id=MySQLdb.connect(__serveur, __user, __passwd, __bdd)
  16.  
  17. c=id.cursor()
  18. c.execute("insert into %s (nom, prenom) values('Victor', 'Paul-Emile')" % __table)
  19. c.execute("insert into %s (nom, prenom) values('Emile', 'Paul-Victor')" % __table)
  20. c.close()
  21. id.commit()
  22. id.close()
  23.  
  24. # Partie 2: Affichage unique
  25. print
  26. print "Affichage"
  27. id=MySQLdb.connect(__serveur, __user, __passwd, __bdd)
  28. c=id.cursor()
  29. c.execute("select * from %s order by nom" % __table)
  30. print c.fetchall()
  31. print "%d lignes\n" % c.rowcount
  32. c.close()
  33. id.close()


 
Donc le principe est de lancer le script1. Il crée la bdd, puis la table, puis il la remplit puis l'affiche et se met en attente d'une frappe clavier.
Pendant qu'il est en attente, on lance le script2 autant de fois qu'on désire. A chaque lancement, il stocke 2 infos dans la table puis l'affiche. On voit ainsi la table grossir.
 
On revient enfin au script1 et on valide la saisie. Le script1 réaffiche le contenu de la table. Théoriquement, on devrait avoir toutes les infos insérées par le script2. Or, sous Windows, on n'a que les infos du début. Si on veut tout avoir, il est nécessaire de refaire un connect(). Il semblerait que l'interface windows d'accès à MySQL conserve en cache les data. Ce problème ne se produit pas sous Linux...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-06-2010 à 10:05:27    

en fait, c'est un problème spécifique aux accès concurrents à partir d'un même programme threadé (en l'occurence le serveur web).
J'ai fini par résoudre mon problème en utilisant une lib qui interface la lib mysqldb et qui gère les threads correctement.
Cette lib s'appelle PySQLPool
Je ne sais plus trop où je l'ai trouvé, mais ça pourrait aider d'autres personnes.
 
Axel

Reply

Marsh Posté le 11-06-2010 à 22:24:21    

axel584 a écrit :

en fait, c'est un problème spécifique aux accès concurrents à partir d'un même programme threadé (en l'occurence le serveur web).
J'ai fini par résoudre mon problème en utilisant une lib qui interface la lib mysqldb et qui gère les threads correctement.
Cette lib s'appelle PySQLPool
Je ne sais plus trop où je l'ai trouvé, mais ça pourrait aider d'autres personnes.
 
Axel


 
Hey, 1 an plus tard !!! vieux motard que jamais  :D  
 
Perso, je suis passé depuis à PostgreSQL et là, zéro soucy. Que ce soit sous Zindow ou Linux (enfin sous Linux c'est normal), les deux scripts ci-dessus portés sous PostgreSQL (psycopg2) fonctionnent comme on est en droit de s'y attendre => les infos écrites par le script2 sont lues dans le script1 sans qu'on ait besoin de se reconnecter. Depuis j'ai adopté PostgreSQL (surtout quand j'ai exploré ses possibilités en matières d'indexation ou de foreign keys :love: :love:  :love:)


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

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