2008-08-03 12 views
21

J'ai créé des tables de base de données (normalisées, sur un serveur MS SQL) et créé une interface 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.Modification d'enregistrements de base de données par plusieurs utilisateurs

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. Ne faites rien et espérez que deux utilisateurs n'éditeront jamais le même enregistrement en même temps. - Peut-être jamais arrivé mais que faire?
  2. La routine d'édition peut stocker une copie des données d'origine ainsi que les mises à jour, puis les comparer lorsque l'utilisateur a terminé l'édition. Si elles diffèrent, afficher la mise à jour de l'utilisateur et de l'entreprise. - Deux copies de données doivent être stockées.
  3. Ajoutez la dernière colonne DATETIME mise à jour et vérifiez qu'elle correspond à la mise à jour, sinon affichez les différences. - requiert une nouvelle colonne dans chacune des tables pertinentes.
  4. Créez une table d'édition qui enregistre lorsque les utilisateurs commencent à modifier un enregistrement qui sera vérifié et empêche les autres utilisateurs d'éditer le même enregistrement. - nécessiterait une réflexion réfléchie sur le déroulement du programme afin d'éviter que les interblocages et les enregistrements ne soient verrouillés si un utilisateur quitte le programme.

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

Répondre

0

La base de données 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.

1

@ Mark Harrison: SQL Server ne prend pas en charge cette syntaxe (SELECT ... FOR UPDATE). L'équivalent de SQL Server est l'indicateur d'instruction SELECTUPDLOCK

Pour plus d'informations, voir SQL Server Books Online pour plus d'informations.

1

Une autre option consiste à vérifier que les valeurs de l'enregistrement que vous changez sont toujours les mêmes comme ils étaient quand vous avez commencé:

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 ça 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 ne devez pas ajouter une nouvelle colonne à votre table (et le maintenir à jour), mais vous devez créer des instructions SQL et plus verbeux passer nouvelle et vieux champs à la procédure stockée.

Il a aussi l'avantage que vous n'êtes pas le verrouillage des enregistrements - parce que nous savons tous que les dossiers finissent par rester verrouillé quand ils ne devraient pas être ...

1

SELECT FOR UPDATE et équivalents sont bons vous offrir tenez le verrou pour une durée microscopique, mais pour un montant macroscopique (par exemple, l'utilisateur a les données chargées et n'a pas appuyé sur 'sauvegarder' vous devriez utiliser la concurrence optimiste comme ci-dessus. (Ce que je pense toujours est mal nommé - c'est plus pessimiste que 'last writer wins', qui est généralement la seule autre alternative considérée.)

2

Une approche classique est la suivante:

  • Ajoutez un champ booléen "verrouillé" à chaque table.
  • définissez cette valeur sur false par défaut.
  • lorsqu'un utilisateur commence l'édition, vous faites ceci:

    • verrouillage de la ligne (ou toute la table si vous ne pouvez pas verrouiller la ligne)
    • vérifier le drapeau sur la ligne que vous souhaitez modifier
    • si le drapeau est vrai, alors
      • informe l'utilisateur qu'ils ne peuvent pas modifier cette ligne au moment
    • autre
      • mis le drapeau à vrai
    • Déverrouillez

    • lors de l'enregistrement du disque, définissez le drapeau de retour à false

+2

Ce n'est pas une bonne chose, si vous définissez le verrou = true, si l'application ou le navigateur tombe en panne, l'enregistrement est définitivement verrouillé. – Cheung

+0

Bon point, @SilverNight - pouvez-vous poster la bonne solution? –

+0

Dans de tels cas (panne de l'application/du navigateur), vous pouvez ajouter la méthode ForceUnlock à l'application, ce qui forcera à la valeur False. – Oleksandr

0

Avec moi , la meilleure façon dont j'ai une colonne lastupdate (timetamp datatype). lorsque sélectionner et mettre à jour il suffit de comparer cette valeur une autre avance de cette solution est que vous pouvez utiliser cette colonne pour traquer 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.

1

-Premier create déposé (temps de mise à jour) pour stocker la dernière mise à jour enregistrement -quand tout utilisateur sélectionner ENREGISTRE de gagner du temps sélectionner comparer entre le temps de sélection et le champ de temps de mise à jour si (temps de mise à jour)> (sélectionner le temps) qui signifie une autre mise à jour par l'utilisateur cet enregistrement après sélection enregistrement

Questions connexes