remplacer les transactions sur MySQL et PHP

remplacer les transactions sur MySQL et PHP - PHP - Programmation

Marsh Posté le 17-10-2003 à 18:12:55    

voila  
 
j'aimerais trouver une methode qui me permettrais de remplacer le système des transactions  (begin, rollback , commit)
sous MySql , etant donné que j'ai une version trop ancienne.
et que je ne peu pas faire de BdD de type innoDB
 
 
merci d'avance

Reply

Marsh Posté le 17-10-2003 à 18:12:55   

Reply

Marsh Posté le 17-10-2003 à 19:16:32    

Tu peux locker les tables dont tu as besoin avant de commencer les modifications.

Reply

Marsh Posté le 20-10-2003 à 09:03:03    

mrBebert a écrit :

Tu peux locker les tables dont tu as besoin avant de commencer les modifications.


 
c'est a dire?
je lock
je fais mon insert
 
et tant ue j'ai pas unlock , les valeurs ne sont pas vraiment insérré?
 
lock ca fait bien le role des transactions?
 
je pensais que ca permettais juste de bloquer l'acces a la base le temps que l'on effectue une acton sur celle-ci , un peu comme le principe des semaphores  non?

Reply

Marsh Posté le 20-10-2003 à 11:04:05    

non, effectivement, tu as raison. Je sais pas pourquoi, j'avais cru comprendre que tu voulais éviter les incohérences dues à des requêtes simultanées.
Ca ne remplace pas les transactions avec la possibilité de les annuler [:proy]

Reply

Marsh Posté le 20-10-2003 à 11:27:44    

mrBebert a écrit :

non, effectivement, tu as raison. Je sais pas pourquoi, j'avais cru comprendre que tu voulais éviter les incohérences dues à des requêtes simultanées.
Ca ne remplace pas les transactions avec la possibilité de les annuler [:proy]  


 
tant pis  :(  merci quand meme
 
si quelqu'una une autre idée ?

Reply

Marsh Posté le 20-10-2003 à 14:17:08    

up

Reply

Marsh Posté le 20-10-2003 à 16:54:05    

Il y a peut être moyen de bricoler :
 
Tu peux faire les insertions dans une table temporaire, que tu recopies ensuite dans la table principale si besoin (ou que tu vides pour annuler). Mais il risque d'y avoir des problèmes si plusieurs threads travaillent en même temps.
 
Ou alors, tu ajoutes une colonne définissant l'id du thread qui effectue l'insertion. Ce numéro devrait être unique. Pour valider, tu positionnes à 0, pour annuler tu supprimes. seules les lignes ayant la valeur 0 sont "bonnes", les autres étant considérées comme étant en attente de validation.
 
Bon, ca reste du bricolage :/

Reply

Marsh Posté le 20-10-2003 à 16:58:37    

mrBebert a écrit :

Il y a peut être moyen de bricoler :
 
Tu peux faire les insertions dans une table temporaire, que tu recopies ensuite dans la table principale si besoin (ou que tu vides pour annuler). Mais il risque d'y avoir des problèmes si plusieurs threads travaillent en même temps.
 
Ou alors, tu ajoutes une colonne définissant l'id du thread qui effectue l'insertion. Ce numéro devrait être unique. Pour valider, tu positionnes à 0, pour annuler tu supprimes. seules les lignes ayant la valeur 0 sont "bonnes", les autres étant considérées comme étant en attente de validation.
 
Bon, ca reste du bricolage :/  


 
en fait ec quej'aimerai c'est:
 
pouvoir annuler toutes mes requtes precedente si par exemple la  3eme  requtes ( de mes requetes successives) plante
 
hors ta solution je ne sais pas si ca resoudrait le pb
parceque uen fois queje fais la copie de la base temporaire a la base réelle bin je risuqe d'avoir le meme pb  non?
 
le commit de la transactions permettrais de tt valider que lorsque l'on saitq ue tt c bien passé  
 
 

Reply

Marsh Posté le 20-10-2003 à 17:00:39    

Y'a tout un tas de façon de faire.
 
1) Comme dit mrBerbet, faire une table temporaire. C'est pas terrible, mais pour certain type de mises à jour c'est ce qui va le mieu.
2) Ajouter un flag "transactionID" contenant l'ID de la transaction en cours sur la ligne à toutes tes tables que tu ne vas passer à true que lorsque toutes tes modifications sont effectuées. Et régulièrement, en batch, deleter toutes les lignes rattachées à des transactions qui ont échouées.
3) Tu peux aussi essayer de bosser avec des transactions macroscopiques. En effet, même si ta version de MySQL ne supporte pas les transactions, logiquement, elle supporte les transactions unitaires, c'est à dire liées à une même commande.
 
Par exemple :
 
delete * from latable where a > 25
 
si le delete plante au milieu à cause de je ne sais quelle raison, normalement aucune ligne n'est supprimée, car il y a une mini-transaction implicite au niveau de la commande elle-même.
 
Donc essaie de voir si tu peux pas t'en tirer en faisant des requêtes plus complexes au lieu de faire une série de requêtes.
 
Sinon, ben voilà quoi... Le SGBD n'étant pas à la base transactionnel, tu pourras pas l'empêcher au final de ne pas l'être. Le seul secret, c'est de ne mettre à jour physiquement tes lignes qu'une fois que la "transaction" est terminée. Mais tu ne seras jamais à l'abrit d'un coupure de courant ou autre connerie qui foutra en l'air ta pseudo transaction.


Message édité par MagicBuzz le 20-10-2003 à 17:01:44
Reply

Marsh Posté le 20-10-2003 à 17:04:07    

en fait, je pense que le coup du flag est la meilleurs solution, mais demande des traîtements très compliqués (duplication et neutralisation des anciennes lignes lorsque tu fais un update par exemple), prise en compte des transactions imbriquées/concurrentes, etc.
 
Un vrai bordel.
 
Par contre, si tu fais ça bien, tu as moyen de faire se comporter la chose comme un vrai SGBD transactionnel, mais à quel prix ! Tu va y passer des mois à mettre au point la gestion des tes flags/réplications/etc. et tu vas avoir des perfs catastrophiques...
 
Le mieu c'est de passer à un SGBD transactionnel, quite à passer sous Access qui gère les transactions...

Reply

Marsh Posté le 20-10-2003 à 17:04:07   

Reply

Marsh Posté le 20-10-2003 à 17:10:34    

MagicBuzz a écrit :

en fait, je pense que le coup du flag est la meilleurs solution, mais demande des traîtements très compliqués (duplication et neutralisation des anciennes lignes lorsque tu fais un update par exemple), prise en compte des transactions imbriquées/concurrentes, etc.
 
Un vrai bordel.
 
Par contre, si tu fais ça bien, tu as moyen de faire se comporter la chose comme un vrai SGBD transactionnel, mais à quel prix ! Tu va y passer des mois à mettre au point la gestion des tes flags/réplications/etc. et tu vas avoir des perfs catastrophiques...
 
Le mieu c'est de passer à un SGBD transactionnel, quite à passer sous Access qui gère les transactions...


 
oauis je crois que je vais rester sur MySql et voir ec que je vais pouvoir faire avce tt ce qui a été dit , mais je crois qu'en effet je vais oublier le flag  :D  
 
ce que je fais pour l'instant c'est  
 
if(query1good)
{
  exec query2
  if(query2good)
  {
   exec query3
  }
}
 
le pb et que si 3 plante
alors que 2 est bonne , bin ca fou le merdier dans mon aplication  ;o)
car il ya auar des données faussés dans certaine tables
 
mais cette methode marche qe si query1 plante  lol
 
 

Reply

Marsh Posté le 20-10-2003 à 17:24:23    

Juste un truc :
 
Avant d'éxécuter tes query, fait tous les tests nécessaires dessus.
 
Je pense notamment à trois choses que tu peux et DOIS testet absolumement avant toute action dans la base :
 
1) Les types des données que tu insères/met à jour sont conformes au modèle de tes données
2) Les clés externes, indexes uniques ne sont pas violés
3) Tous les chmps "NOT NULL" contiendront une valeur après ta requête
 
En effet, no seulement ça résoudra par là même ton problème, mais en plus :
- Le jour où tu passeras sur un projet style ERP, tu découvriras qu'AUCUNE règle de gestion n'est contenune dans la base (tout au plus des indexes uniques), c'est à l'applicatif de garantir la cohérence des données
- C'est bien plus propre de gérer soit-même les erreurs avant que ce soit le système qui les génère. Car autant tu peux être sûr des tests que tu fais, autant tu n'es pas à l'abrit de la désactivation d'une règle dans la base par exemple
- Niveau performances, contrairement à ce qu'on peut penser, il est plus rapide de faire les vérification avant d'inserrer une ligne (même si on fait des insert/update) que de faire ces mises à jour avec la commande "CHECK" activée (toujours désactivée sur un gros système, ce qui permet de violer des contraintes sans problème, mais surtout de conserver de bonnes perfs sur des tables de quelques milliards de lignes).
En effet, imagine une table de 10 milliards d'enregistrement.
Une autre table qui y fait référence, avec une clé étrangère qui pointe sur 25 champs de la première... Quand tu vas ajouter une ligne, tu vas te palucher 25 champs de 10 milliards de lignes pour vérifier que tu ne violes pas une clé... (le système le fera implicitement si la clé est définie). Alors que si tes 25 valeurs proviennent d'un écran où c'était des selectbox provenant de ta table, tu est certain qu'elles sont bonnes, donc tu n'a pas besoin de vérifier.
 
En somme, à toi de garantir que tes requêtes ne génèreront pas d'erreur avant de faire les modifs. Il ne restera plus que les gros problèmes système (limite espace disque, coupure de courant, lock, etc.)

Reply

Marsh Posté le 20-10-2003 à 17:28:42    

MagicBuzz a écrit :

Juste un truc :
 
Avant d'éxécuter tes query, fait tous les tests nécessaires dessus.
 
Je pense notamment à trois choses que tu peux et DOIS testet absolumement avant toute action dans la base :
 
1) Les types des données que tu insères/met à jour sont conformes au modèle de tes données
2) Les clés externes, indexes uniques ne sont pas violés
3) Tous les chmps "NOT NULL" contiendront une valeur après ta requête
 
En effet, no seulement ça résoudra par là même ton problème, mais en plus :
- Le jour où tu passeras sur un projet style ERP, tu découvriras qu'AUCUNE règle de gestion n'est contenune dans la base (tout au plus des indexes uniques), c'est à l'applicatif de garantir la cohérence des données
- C'est bien plus propre de gérer soit-même les erreurs avant que ce soit le système qui les génère. Car autant tu peux être sûr des tests que tu fais, autant tu n'es pas à l'abrit de la désactivation d'une règle dans la base par exemple
- Niveau performances, contrairement à ce qu'on peut penser, il est plus rapide de faire les vérification avant d'inserrer une ligne (même si on fait des insert/update) que de faire ces mises à jour avec la commande "CHECK" activée (toujours désactivée sur un gros système, ce qui permet de violer des contraintes sans problème, mais surtout de conserver de bonnes perfs sur des tables de quelques milliards de lignes).
En effet, imagine une table de 10 milliards d'enregistrement.
Une autre table qui y fait référence, avec une clé étrangère qui pointe sur 25 champs de la première... Quand tu vas ajouter une ligne, tu vas te palucher 25 champs de 10 milliards de lignes pour vérifier que tu ne violes pas une clé... (le système le fera implicitement si la clé est définie). Alors que si tes 25 valeurs proviennent d'un écran où c'était des selectbox provenant de ta table, tu est certain qu'elles sont bonnes, donc tu n'a pas besoin de vérifier.
 
En somme, à toi de garantir que tes requêtes ne génèreront pas d'erreur avant de faire les modifs. Il ne restera plus que les gros problèmes système (limite espace disque, coupure de courant, lock, etc.)


 
 
ouais c'est calir , j'essaye d efaire tt ca , mais il ya toujours des trucs qui nous echappes   :(


Message édité par saxgard le 20-10-2003 à 17:28:56
Reply

Marsh Posté le 20-10-2003 à 17:29:44    

c pour quoi tes transactions au fait ?

Reply

Marsh Posté le 20-10-2003 à 17:34:04    

MagicBuzz a écrit :

c pour quoi tes transactions au fait ?


 
bin c'est pour ce qu'on dit depuis tt a l'heure c'ets pour eviter d'enregistrer dans mes tables tantq ue je suis pas sur que tt est bon et qu'il n'ya aucun pb dans toutes les autres requtes que je fais a la suite ;o)

Reply

Marsh Posté le 20-10-2003 à 17:37:51    

ouais, nan mais c koi ton application ?
 
quelle fonction ?
 
parceque perso, j'ai jamais eu besoin vraiment de transactions. donc c'est pour ça, j'ai peut-être déjà eu le problème face à moi, et j'ai trouvé une bidouille permettant de pallier au problème.

Reply

Marsh Posté le 20-10-2003 à 17:43:39    

MagicBuzz a écrit :

ouais, nan mais c koi ton application ?
 
quelle fonction ?
 
parceque perso, j'ai jamais eu besoin vraiment de transactions. donc c'est pour ça, j'ai peut-être déjà eu le problème face à moi, et j'ai trouvé une bidouille permettant de pallier au problème.


 
je dois faire une application qui permet de referencer des produits
par consequent quand on reference des produist je les met dans  2 tables (une table historique et une table produit)
 
ensuite une personne doit valider si le produit est corrcte ou non avant de le mettre dans une base Oracle.
 
quand cette personne valide le produit  alors celui-ci est supprimé de la table produit , il y a une ligne qui se rajoute dans la table historique  et ce produit ce met dans une table validation  :D  
 
par consequent si une requete plante il y a une etape qui peu pas se faire comme : la mise du produit dans l'historique ou la suppression du produit dans la table produit  
 
etc..
 
c'est presque clair?  :)


Message édité par saxgard le 20-10-2003 à 17:48:46
Reply

Marsh Posté le 20-10-2003 à 18:25:02    

euh... et si vous avez une DB oracle, pourquoi vous pouvez pas mettre les tables dedans directement?

Reply

Marsh Posté le 20-10-2003 à 18:34:49    

gizmo a écrit :

euh... et si vous avez une DB oracle, pourquoi vous pouvez pas mettre les tables dedans directement?


 
en fait tout l'appli est sur un intranet en PHP et MySQL , la base oracle c'est avec un ERP , je ne travail pas directemnt dessus , c'est bien trop compliqué  
 
en fait moi je ne rajoute pas directement les produits dans cette base oracle , je fais un fichier qui contient les produits et ensuite qui est integré dans l'ERP  
 
hmm en gros c un peu compliqué  ;o)
 
et puis la base oracle c'ets pas moi qui l'es fait  , puis d ette fcaon vaut eux d'abord travailler sur uen base locale MySQL et quand tt est controlé etc.. alors on fait le transfert sur la base oracle


Message édité par saxgard le 20-10-2003 à 18:35:50
Reply

Marsh Posté le 20-10-2003 à 18:53:14    

ok, donc si c'est un intranet, vous ne pouvez pas utiliser un DBMS digne de ce nom? comme postgreSQL?

Reply

Marsh Posté le 20-10-2003 à 18:57:06    

gizmo a écrit :

ok, donc si c'est un intranet, vous ne pouvez pas utiliser un DBMS digne de ce nom? comme postgreSQL?


 
la question n'est pas la
je doit d'abord faire avec ce que j'ai , ou ce qu'on m'impose  ;o)
 
puis des fois on ne peu pas svoir ce qu'une BdD va nous poser comme pb.
 
par rapport au projet MySQL et PHP me semblait nettemnt suffisant
c'est gratuit et ca tourne sous Windows

Reply

Marsh Posté le 20-10-2003 à 19:19:44    

T'as pas besoin de transation pour ça.
 
Suffit de :
- faire l'ajout dans l'historique en premier.
- faire l'update dans la table produit.
- deleter le produit de la table temporaire.
 
En effet :
-> si l'appli plante, tu ajoutes une ligne dans la ligne historique, ça te fera un log en plus
-> si tu insèrres le fichier, de toute façon le delete ne pourra en aucun cas planter (à moins que tu aies des jointures, ce qui est vraiment pas judicieux pour une table temporaire) donc pas besoin de pouvoir annuler.

Reply

Marsh Posté le 21-10-2003 à 09:54:41    

MagicBuzz a écrit :

T'as pas besoin de transation pour ça.
 
Suffit de :
- faire l'ajout dans l'historique en premier.
- faire l'update dans la table produit.
- deleter le produit de la table temporaire.
 
En effet :
-> si l'appli plante, tu ajoutes une ligne dans la ligne historique, ça te fera un log en plus
-> si tu insèrres le fichier, de toute façon le delete ne pourra en aucun cas planter (à moins que tu aies des jointures, ce qui est vraiment pas judicieux pour une table temporaire) donc pas besoin de pouvoir annuler.


 
ouais j'ai deja reflechis sur l'ordre a prendre dans mes requetes ,mais je crois que je mettais rendu compte que ca pouvais quand meme deconnera un moment donner
Mais c vraiq ue la solution de mettre d'abord dans l'historique est bonne.
Cela dit il faudrait par la suite que je fasse une parti administration qui permette de récuperer le produit quia  planté a partir de l'historique (que de boulot   :(  ) lol

Reply

Marsh Posté le 21-10-2003 à 11:56:28    

Citation :

voila  
 
j'aimerais trouver une methode qui me permettrais de remplacer le système des transactions  (begin, rollback , commit)
sous MySql , etant donné que j'ai une version trop ancienne.
et que je ne peu pas faire de BdD de type innoDB
 
 
merci d'avance


 
Franchement tu devrais mettre MySQL a jour ou bien utiliser PostgreSQL si tu veux vraiment des transactions (PostgreSQL est gratuit aussi et tourne sous Win).
 
EDIT : au fait, pourquoi tu ne peux pas creer des tables InnoDB? Tu sais qu'on peut mixer plusieurs types de tables dans une meme db?


Message édité par impulse le 21-10-2003 à 12:00:53
Reply

Marsh Posté le 21-10-2003 à 12:09:54    

impulse a écrit :

Citation :

voila  
 
j'aimerais trouver une methode qui me permettrais de remplacer le système des transactions  (begin, rollback , commit)
sous MySql , etant donné que j'ai une version trop ancienne.
et que je ne peu pas faire de BdD de type innoDB
 
 
merci d'avance


 
Franchement tu devrais mettre MySQL a jour ou bien utiliser PostgreSQL si tu veux vraiment des transactions (PostgreSQL est gratuit aussi et tourne sous Win).
 
EDIT : au fait, pourquoi tu ne peux pas creer des tables InnoDB? Tu sais qu'on peut mixer plusieurs types de tables dans une meme db?


 
pour ca aussi il faut une version plus recente de mysql  ;o)

Reply

Marsh Posté le 21-10-2003 à 13:40:11    

pas besoin d'une version plus récente, faut le configurer correctement.

Reply

Marsh Posté le 21-10-2003 à 13:42:35    

drasche a écrit :

pas besoin d'une version plus récente, faut le configurer correctement.


 
on le configure ou? , parceque j'ai pris easyphp
 
cela dis une fois que j'ai mes tables innoDB, a quoi cela me sert si je peu pas pas utiliser els transactions?
 
c'est utiles pour quoi?  

Reply

Marsh Posté le 21-10-2003 à 13:46:40    

si tu sais utiliser les tables InnoDB, tu sais utiliser les transactions; c'est le but de ce type de tables justement, en plus de savoir gérer les contraintes de clés étrangères.


Message édité par drasche le 21-10-2003 à 13:47:10
Reply

Marsh Posté le 21-10-2003 à 14:11:02    

drasche a écrit :

si tu sais utiliser les tables InnoDB, tu sais utiliser les transactions; c'est le but de ce type de tables justement, en plus de savoir gérer les contraintes de clés étrangères.


 
bah justement je maitrise pas  ;o)

Reply

Marsh Posté le 21-10-2003 à 14:22:53    

Citation :

on le configure ou? , parceque j'ai pris easyphp


 
Ne me dis pas que tu ne *peux* pas installer MySQL 4.x parce que tu utilises EasyPHP...
Y'en a pour 5 minutes pour installer Apache+PHP+MySQL a la main sous Windows.

Reply

Marsh Posté le 21-10-2003 à 14:24:13    

tu devrais avoir des exemples de fichiers my.conf dans l'installation de MySQL (pourvu que EasyPHP les ait installés). Je pense que dans chacun de ces exemples, une configuration type est donnée pour activer InnoDB. Ils se nomment my-*.conf, mais sous Windows, ils apparaissent comme des shortcuts de type speeddial [:kiki]
 
Je te colle un exemple ici:

Code :
  1. # Uncomment the following if you are using Innobase tables
  2. #innodb_data_file_path = ibdata1:100M
  3. #innodb_data_home_dir = c:\ibdata
  4. #innodb_log_group_home_dir = c:\iblogs
  5. #innodb_log_arch_dir = c:\iblogs
  6. #set-variable = innodb_mirrored_log_groups=1
  7. #set-variable = innodb_log_files_in_group=3
  8. #set-variable = innodb_log_file_size=5M
  9. #set-variable = innodb_log_buffer_size=8M
  10. #innodb_flush_log_at_trx_commit=1
  11. #innodb_log_archive=0
  12. #set-variable = innodb_buffer_pool_size=16M
  13. #set-variable = innodb_additional_mem_pool_size=2M
  14. #set-variable = innodb_file_io_threads=4
  15. #set-variable = innodb_lock_wait_timeout=50

Reply

Marsh Posté le 21-10-2003 à 14:43:02    

drasche a écrit :

tu devrais avoir des exemples de fichiers my.conf dans l'installation de MySQL (pourvu que EasyPHP les ait installés). Je pense que dans chacun de ces exemples, une configuration type est donnée pour activer InnoDB. Ils se nomment my-*.conf, mais sous Windows, ils apparaissent comme des shortcuts de type speeddial [:kiki]
 
Je te colle un exemple ici:

Code :
  1. # Uncomment the following if you are using Innobase tables
  2. #innodb_data_file_path = ibdata1:100M
  3. #innodb_data_home_dir = c:\ibdata
  4. #innodb_log_group_home_dir = c:\iblogs
  5. #innodb_log_arch_dir = c:\iblogs
  6. #set-variable = innodb_mirrored_log_groups=1
  7. #set-variable = innodb_log_files_in_group=3
  8. #set-variable = innodb_log_file_size=5M
  9. #set-variable = innodb_log_buffer_size=8M
  10. #innodb_flush_log_at_trx_commit=1
  11. #innodb_log_archive=0
  12. #set-variable = innodb_buffer_pool_size=16M
  13. #set-variable = innodb_additional_mem_pool_size=2M
  14. #set-variable = innodb_file_io_threads=4
  15. #set-variable = innodb_lock_wait_timeout=50




 
je regarderais ca , je te remercie

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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