Modification des enregistrements de base de données par plusieurs utilisateurs

StackOverflow https://stackoverflow.com/questions/833

  •  08-06-2019
  •  | 
  •  

Question

J'ai conçu des tables de base de données (normalisées, sur un serveur MS SQL) et créé un frontal Windows autonome pour une application qui sera utilisée par une poignée d'utilisateurs pour ajouter et modifier des informations.Nous ajouterons ultérieurement une interface Web pour permettre la recherche dans notre zone de production.

Je crains que si deux utilisateurs commencent à modifier le même enregistrement, le dernier à valider la mise à jour sera le « gagnant » et des informations importantes risquent d'être perdues.Un certain nombre de solutions me viennent à l'esprit, mais je ne suis pas sûr de créer un plus gros casse-tête.

  1. Ne faites rien et espérez que deux utilisateurs ne modifieront jamais le même enregistrement en même temps. - Cela n'arrivera peut-être jamais, mais et si c'était le cas ?
  2. La routine d'édition pourrait stocker une copie des données originales ainsi que les mises à jour, puis comparer lorsque l'utilisateur a terminé l'édition.S'ils diffèrent, affichez l'utilisateur et confirmez la mise à jour - Nécessiterait le stockage de deux copies des données.
  3. Ajoutez la dernière colonne DATETIME mise à jour et vérifiez qu'elle correspond lors de la mise à jour, sinon affichez les différences. - nécessite une nouvelle colonne dans chacun des tableaux concernés.
  4. Créez une table d'édition qui enregistre le moment où les utilisateurs commencent à modifier un enregistrement qui sera vérifié et empêchera les autres utilisateurs de modifier le même enregistrement. - nécessiterait une réflexion approfondie sur le déroulement du programme pour éviter les blocages et le verrouillage des enregistrements si un utilisateur plante hors du programme.

Existe-t-il de meilleures solutions ou dois-je opter pour l'une d'elles ?

Était-ce utile?

La solution

Si vous vous attendez à des collisions peu fréquentes, Concurrence optimiste est probablement votre meilleur pari.

Scott Mitchell a écrit un tutoriel complet sur la mise en œuvre de ce modèle :
Implémentation de la concurrence optimiste

Autres conseils

Une approche classique est la suivante :

  • ajoutez un champ booléen, "verrouillé" à chaque table.
  • définissez ceci sur false par défaut.
  • lorsqu'un utilisateur commence à éditer, vous faites ceci :

    • verrouillez la ligne (ou la table entière si vous ne pouvez pas verrouiller la ligne)
    • cochez le drapeau sur la ligne que vous souhaitez modifier
    • si le drapeau est vrai alors
      • informer l'utilisateur qu'il ne peut pas modifier cette ligne pour le moment
    • autre
      • mettre le drapeau sur vrai
    • libérer le verrou

    • lors de la sauvegarde de l'enregistrement, remettez l'indicateur sur false

SELECT FOR UPDATE et équivalents sont bons à condition que vous mainteniez le verrou pendant une durée microscopique, mais pendant une durée macroscopique (par ex.l'utilisateur a chargé les données et n'a pas appuyé sur « enregistrer », vous devez utiliser la concurrence optimiste comme ci-dessus.(Ce que je pense toujours est mal nommé - c'est plus pessimiste que « le dernier écrivain gagne », qui est généralement la seule autre alternative envisagée.)

@Marc Harrison :SQL Server ne prend pas en charge cette syntaxe (SELECT ... FOR UPDATE).

L'équivalent de SQL Server est le SELECT indice de déclaration UPDLOCK.

Voir Livres SQL Server en ligne pour plus d'informations.

-Enter Créer Filed (Temps de mise à jour) pour stocker le dernier enregistrement de mise à jour - Quand tout utilisateur Sélectionnez enregistrer l'heure Sélectionnez, comparez entre Sélectionner l'heure et le champ de temps de mise à jour si (temps de mise à jour)> (Sélectionner l'heure) qui signifie une autre mise à jour de l'utilisateur cet enregistrement après la sélection enregistrer

Une autre option consiste à tester que les valeurs de l'enregistrement que vous modifiez sont toujours les mêmes qu'au début :

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(afficher le champ customer_nm et l'utilisateur le modifie)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

Vous n'êtes pas obligé d'ajouter une nouvelle colonne à votre table (et de la maintenir à jour), mais vous devez créer des instructions SQL plus détaillées et transmettre nouveau et vieux champs à la procédure stockée.

Cela présente également l'avantage de ne pas verrouiller les enregistrements - car nous savons tous que les enregistrements finiront par rester verrouillés alors qu'ils ne devraient pas l'être...

La base de données le fera pour vous.Regardez "sélectionner...for update", qui est conçu uniquement pour ce genre de chose.Cela vous donnera un verrou en écriture sur les lignes sélectionnées, que vous pourrez ensuite valider ou annuler.

Avec moi, la meilleure façon d'avoir une dernière mise à jour de colonne (type de données d'horodatage).Lorsque la sélection et la mise à jour comparent simplement cette valeur, une autre avancée de cette solution est que vous pouvez utiliser cette colonne pour retrouver les données de temps.Je pense que ce n'est pas bien si vous créez simplement une colonne comme isLock pour vérifier la mise à jour.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top