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

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

Je suis préoccupé par le fait que si deux utilisateurs commencent à éditer le même enregistrement, le dernier à valider la mise à jour serait le 'gagnant' et des informations importantes pourraient être perdues. Un certain nombre de solutions me viennent à l'esprit mais je ne suis pas sûr si je vais créer un plus gros mal de tête.

  1. Do nothing and hope that two users are never going to be editing the same record at the same time. - Might never happed but what if it does?
  2. Editing routine could store a copy of the original data as well as the updates and then compare when the user has finished editing. If they differ show user and comfirm update - Would require two copies of data to be stored.
  3. Add last updated DATETIME column and check it matches when we update, if not then show differences. - requires new column in each of the relevant tables.
  4. Create an editing table that registers when users start editing a record that will be checked and prevent other users from editing same record. - would require carful thought of program flow to prevent deadlocks and records becoming locked if a user crashes out of the program.

Y a-t-il de meilleures solutions ou dois-je choisir l'une de ces solutions?

0
ajouté édité
Vues: 7

7 Réponses

La base de données le fera pour vous. Regardez "sélectionnez ... pour la mise à jour", qui est conçu uniquement pour ce genre de chose. Il vous donnera un verrou en écriture sur les lignes sélectionnées, que vous pourrez ensuite valider ou annuler.

0
ajouté

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

Scott Mitchell wrote a comprehensive tutorial on implementing that pattern:
Implementing Optimistic Concurrency

0
ajouté
Merci d'avoir partagé.
ajouté l'auteur Pramod Gharu, source

@ Mark Harrison: SQL Server ne supporte pas cette syntaxe ( SELECT ... FOR UPDATE ).

L'équivalent SQL Server est l'indicateur d'instruction SELECT UPDLOCK .

Pour plus d'informations, consultez la page Documentation en ligne de SQL Server .

0
ajouté

Une autre option consiste à tester que les valeurs de l'enregistrement que vous modifiez sont toujours les mêmes que lorsque vous avez démarré:

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

(affiche le champ customer_nm et l'utilisateur le change)

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'avez pas besoin d'ajouter une nouvelle colonne à votre table (et de la maintenir à jour), mais vous devez créer des instructions SQL plus verbeuses et passer new et old champs à la procédure stockée.

Cela a aussi l'avantage que vous ne verrouillez pas les dossiers - parce que nous savons tous que les dossiers finiront par rester verrouillés alors qu'ils ne devraient pas l'être ...

0
ajouté

Une approche classique est la suivante:

  • add a boolean field , "locked" to each table.
  • set this to false by default.
  • when a user starts editing, you do this:

    • lock the row (or the whole table if you can't lock the row)
    • check the flag on the row you want to edit
    • if the flag is true then
      • inform the user that they cannot edit that row at the moment
    • else
      • set the flag to true
    • release the lock

    • when saving the record, set the flag back to false

0
ajouté
Ce n'est pas une bonne chose, si lock = true, si l'application ou le navigateur tombe en panne, alors l'enregistrement est verrouillé à jamais.
ajouté l'auteur Cheung, source
C'est la solution du drapeau blanc "résoudre les modifications simultanées est difficile, donc je vais arrêter"
ajouté l'auteur Chris Marisic, source
Bon point, @SilverNight - pouvez-vous poster la bonne solution?
ajouté l'auteur AJ., source
Dans de tels cas (crash de l'application / navigateur), vous pouvez ajouter la méthode ForceUnlock à l'application, ce qui va forcer Lock à False.
ajouté l'auteur Oleksandr, source

Avec moi, la meilleure façon d'avoir une colonne lastupdate (timetamp datatype). lorsque sélectionner et mettre à jour, comparez simplement cette valeur Une autre avancée de cette solution est que vous pouvez utiliser cette colonne pour suivre le temps que les données ont changé. Je pense que ce n'est pas bien si vous créez juste une colonne comme isLock pour la mise à jour de vérification.

0
ajouté

-first create filed (update time) to store last update record -when any user select record save select time, compare between select time and update time field if( update time) > (select time) that mean another user update this record after select record

0
ajouté