8
votes

MySQL Row verrouillage par PHP

J'aids un ami avec une forme Web basée sur le Web destiné à leur entreprise. J'essaie de le préparer à gérer plusieurs utilisateurs. Je l'ai configuré de sorte que juste avant que l'enregistrement ne soit affiché pour l'édition, je verrouille l'enregistrement avec le code suivant.

START TRANSACTION;
SELECT field FROM table WHERE ID = "40" FOR UPDATE;


1 commentaires

Qu'avez-vous fait après la deuxième seconde mysql_query ($ requis); ? Si votre script PHP quitte, puis verrouiller la libération


5 Réponses :


0
votes

Utilisez PDO pour cette (et toutes les opérations de base de données):

mysql_query('SET AUTOCOMMIT=0');
mysql_query('START TRANSACTION');
mysql_query($sql);
mysql_query('SET AUTOCOMMIT=1');


2 commentaires

Ne pas descendre en silence. Laissez un commentaire pour aider à mieux répondre.


Pour le dossier, je ne vois pas de problème avec cette suggestion, il fait penser à la pensée!



0
votes

Le problème sont les commandes MySQL. Vous pouvez utiliser mysqli pour cette

http://nz.php.net/manual/fr/class .mysqli.php

ou PDO. Décrit ici:

PHP + MySQL Exemples

htth


1 commentaires

Je suis d'accord avec webbiedave. S'il vous plaît laissez-moi savoir pourquoi vous l'avez fait et comment améliorer, cela vous aiderait, moi et la communauté. Merci!



0
votes

Vous ne devez pas utiliser l'API MySQL car il est facile de faire des erreurs qui permet des injections SQL et de telles fonctionnalités. Je soupçonne que la transaction en fait partie parce que si je ne me trompe pas, chaque requête est envoyée "par elle-même" et pas dans un contexte plus important.

La solution est toutefois d'utiliser une autre API, je préfère MySQLI parce que c'est tellement similaire à MySQL et largement soutenu. Vous pouvez facilement réécrire votre code pour utiliser MySQLI à la place.

Pour la fonctionnalité de transaction SET Auto-COMMENCTEZ à FAUX et engagez-vous lorsque vous le souhaitez. Cela fait la même chose que les transactions de démarrage et d'arrêt.

Pour le registre de référence sur:

http://www.php.net/manual/fr/mysqli. autocommet.php

http://www.php.net/manual/fr/mysqli. commit.php


0 commentaires

13
votes

Le problème n'est pas la syntaxe de votre code, mais la façon dont vous essayez de l'utiliser.

juste avant que l'enregistrement ne soit affiché pour l'édition, je verrouille l'enregistrement avec le code suivant

De cela, je suppose que vous sélectionnez et "verrouiller" la ligne, puis affichez cette page d'édition sur votre utilisateur, puis lorsqu'ils soumettent les modifications qu'il enregistre et "déverrouille" la table. Ici dans réside le problème fondamental. Lorsque votre page est terminée Chargement, la PHP quitte et ferme la connexion MySQL. Lorsque cela se produit, tous les serrures sont immédiatement libérés. C'est pourquoi la console semble se comporter différemment de votre PHP. L'équivalent de la console serait que vous quitteriez le programme.

Vous ne pouvez pas verrouiller les rangées de table pour l'édition pendant une période prolongée. Ce n'est pas leur conception. Si vous souhaitez verrouiller un enregistrement pour l'édition, vous devez suivre ces serrures dans une autre table. Créez une nouvelle table appelée "EDIT_LOCKS" et stockez l'ID d'enregistrement en cours de verrouillage, l'édition de l'ID utilisateur et l'heure à laquelle il était verrouillé. Lorsque vous souhaitez ouvrir un enregistrement pour l'édition, verrouillez la table EDIT_Locks entière et requête pour voir si l'enregistrement est verrouillé par quelqu'un d'autre. Si ce n'est pas le cas, insérez votre enregistrement de verrouillage, s'il s'agit, puis affichez une erreur verrouillée. Lorsque l'utilisateur enregistre ou annule, retirez l'enregistrement de verrouillage de EDIT_LOCKS. Si vous voulez faciliter les choses, verrouillez simplement cette table à tout moment votre programme souhaite l'utiliser. Cela vous aidera à éviter une condition de race.

Il y a un autre scénario qui peut causer un problème. Si l'utilisateur ouvre un enregistrement pour l'édition, puis ferme le navigateur sans enregistrer ou annuler, le verrouillage d'édition restera pour toujours. C'est pourquoi j'ai dit stocker le temps qu'il a été verrouillé. L'éditeur lui-même devrait faire un appel Ajax toutes les 2 minutes environ pour dire "J'ai toujours besoin de la serrure!". Lorsque le programme PHP reçoit cette requête «Relock», elle doit rechercher le verrou, puis mettez à jour l'horodatage sur le courant. De cette façon, l'horodatage sur la serrure est toujours à jour dans les 2 minutes. Vous devez également créer un autre programme pour éliminer les anciens serrures contaminés. Cela devrait courir dans un travail cron toutes les quelques minutes. Il devrait rechercher des serrures avec un horodatage de plus de 5 minutes environ, et d'enlever. Si l'horodatage est plus âgé que cela, il est clair que l'éditeur était proche de la façon dont ou l'horodatage serait à jour dans les 2 minutes.

Comme si certains des autres ont mentionné, vous devriez essayer d'utiliser mysqli . Il représente "MySQL amélioré" et est le remplacement de l'ancienne interface.


6 commentaires

Cette façon de le faire a quelques avantages mais aussi quelques inconvénients. Vous aurez besoin d'un nettoyage pour votre table de verrouillage / déverrouillage de temps en temps. Ceci est causé par des accidents ou des distractions inattendues. Personnellement, je ne l'utiliserais pas.


D'accord Jmack, vous avez prolongé votre réponse maintenant et avez expliqué les inconvénients de votre deuxième partie. Réponse solide +1


@Andreas inclus dans ma description est une méthode permettant de nettoyer la table de verrouillage de manière à ce que tout brancher du navigateur entraîne un verrouillage d'enregistrement inférieur à quelques minutes.


@Andreas Oops, nous sommes hors de synchronisation un peu. On dirait que nous sommes sur la même page cependant.


Merci beaucoup. Vous frappez définitivement mon problème. Donc, si vous devez implémenter vous-même l'intégralité du schéma de verrouillage, vous utilisez-t-il une utilisation pour «Select... Pour mettre à jour"?


Je dirais non. Je ne peux penser à aucune raison d'utiliser le verrouillage de niveau de ligne pour ce scénario. Il suffit de verrouiller la table "Editer_Locks" à chaque fois que vous devez l'utiliser et que vous devriez être prêt à partir.



1
votes

C'est une vieille discussion, mais peut-être que les gens le suivent toujours. J'utilise une méthode similaire à celle de Jmack, mais incluez les informations de verrouillage dans le tableau que je souhaite la ligne à ligne. Mes nouvelles colonnes sont verrouillées et verrouillées. Pour tenter un verrou, je fais:

UPDATE table
SET LockTime=NULL,LockedBy=''
WHERE Key='$value' AND LockedBy='$Userid'


0 commentaires