2009-05-31 4 views
0

J'essaie de trouver un moyen efficace de permettre à un groupe de personnes de travailler dans une file d'attente de tâches de saisie de données. Auparavant, nous venions d'avoir une personne qui faisait cela, donc ça n'a pas été un problème. Le back-end est un SGBDR et le frontal est une application web.Affectation de tâches de saisie de données à plusieurs utilisateurs d'applications Web simultanés

Actuellement nous faisons quelque chose comme ceci:

Pour attribuer un record pour l'édition:

SELECT * FROM records WHERE in_edit_queue LIMIT 1; 

Ensuite,

Pour enregistrer les modifications apportées à un enregistrement attribué précédemment:

UPDATE records SET ..., in_edit_queue = false 
    WHERE id = ? AND in_edit_queue = true; 

Cela signifie qu'il est possible que deux utilisateurs se voient attribuer le même enregistrement t, et nous privilégions la première qui présente, à défaut en silence sur les observations suivantes, par exemple:

  1. utilisateur A charge jusqu'à enregistrement 321 pour l'édition
  2. charges utilisateur B jusqu'à enregistrement 321 pour l'édition
  3. soumet l'utilisateur B les changements (ils sont enregistrés dans la base de données)
  4. utilisateur A présente des changements (ils ne sont pas enregistrés dans le DB)

(note: Nous pouvons faire confiance à tous nos utilisateurs de soumettre des données acceptables, donc il n'y a pas besoin pour nous de garder les données de la Le deuxième problème avec cette méthode est que lorsque les utilisateurs démarrent en même temps et éditent à peu près à la même vitesse, ils mettent souvent à jour les mêmes enregistrements mais seulement 1 d'entre eux est sauvegardé. En d'autres termes, gaspiller beaucoup d'heures-homme. Je peux atténuer cela dans une certaine mesure en choisissant des rangées aléatoires, mais je préférerais quelque chose d'un peu plus garanti.

Alors, voici ce que je pense ...

ont une table appelée: locked_records (record_id integer, locked_until timestamp)

-- Assign a record for editing: 
-- Same as before but also make sure the 
-- record is not listed in locked_records... 
SELECT * FROM records 
    WHERE in_edit_queue AND id NOT IN (
    SELECT record_id FROM locked_records 
    WHERE locked_until > now()) 
    LIMIT 1; 

-- ..and effectively remove it from 
-- the queue for the next 5 minutes 
INSERT INTO locked_records (record_id, locked_until) 
    VALUES (?, now() + 300); 

Puis:

UPDATE records SET ..., in_edit_queue = false 
    WHERE id = ? AND in_edit_queue = true; 
DELETE FROM locked_records WHERE record_id = ?; 

Une édition typique prend environ 30 secondes à 1 minute , 5 minutes sur la file d'attente devrait être une bonne quantité. Je peux aussi avoir un XHR sur l'application web continue à mettre à jour le verrou si cela s'avérait avantageux.

Quelqu'un peut-il offrir des idées là-dessus? Cela ressemble à une bonne façon de faire les choses? Cela ressemble à une manière terrible? Fait cela avant? J'aimerais entendre des commentaires.

Merci! J

Répondre

0

Qu'en est-il de la liste interne des verrous des SGBDR? Est-ce que modifier l'instruction SELECT pour qu'elle soit SELECT FOR UPDATE soit une option?

+0

Je ne pense pas, puisque la mise à jour se produira à travers une connexion de base de données différente car c'est une application web. Ou pas du tout, comme encore .. c'est une application web :-) Si je ne comprends pas quelque chose s'il vous plaît faites le moi savoir ... –

+0

p.s. Si vous envisagiez de conserver une table locked_records séparée, alors oui, je pense que cela fonctionnerait et serait plus élégant, mais la table 'records' est constamment lue par des utilisateurs non éditables et je ne veux pas la verrouiller c'est pour cette raison. –

+0

La possibilité qu'une autre connexion DB puisse être utilisée devrait être évaluée; Vous avez raison de dire qu'un SELECT FOR UPDATE ne fonctionnera pas dans ce scénario. Une commande SELECT FOR UPDATE ne devrait pas empêcher les lecteurs d'accéder à la plupart des SGBDR, vous devrez vérifier les docos pour votre compte. – Karl

0

Autre idée: ces enregistrements comportent deux colonnes supplémentaires: assigned_to et completed.

Quand quelqu'un veut modifier un enregistrement, faire quelque chose comme

update records set assigned_to = ? # assigning to 'me' 
where assigned_to is null 
and completed = false 
limit 1 # only assign one record at a time 

Ensuite, pour obtenir cette rangée:

select ... 
from records 
where assigned_to = ? # assigned to 'me' 
and completed = false 

Et une fois que vous avez fini le définissez terminé à « true '. Vous pouvez avoir une colonne d'horodatage supplémentaire lorsqu'un enregistrement a été attribué à quelqu'un, puis ajouter une alternative OR à la partie "assigned_to is null" de la clause where dans l'instruction update ci-dessus, où vous avez besoin d'une certaine énumération pour qu'une assignation soit valide.

Questions connexes