2010-09-22 4 views
8

Je veux verrouiller un enregistrement et personne ne peut apporter de modifications à cet enregistrement. Lorsque je relâche la serrure, les gens peuvent changer le dossier.Comment effectuer un verrouillage de ligne?

En attendant qu'un enregistrement est verrouillé, je veux montrer à l'utilisateur un avertissement que l'enregistrement est verrouillé et que les modifications ne sont pas autorisées.

Comment est-ce que je peux faire ceci?

J'ai essayé tous les niveaux IsolationLevel, mais aucun d'entre eux n'a le comportement que je veux. Certains niveaux d'isolement attendent que le verrou soit libéré et effectuent ensuite un changement. Je ne le veux pas, car la mise à jour n'est pas autorisée au moment où un enregistrement est verrouillé. Que puis-je faire pour verrouiller un enregistrement et refuser toutes les modifications?

J'utilise SQL Server 2008

+0

Cela dépend de la base de données. Laquelle? – pascal

+0

SQL Server 2008 – Martijn

Répondre

0

Voir cette duplicate question sur le SO.

Fondamentalement, il est:

begin tran 

select * from [table] with(holdlock,rowlock) where id = @id 

--Here goes your stuff 

commit tran 

Archive

Quelque chose comme ça peut-être?

update t 
set t.IsLocked = 1 
from [table] t 
where t.id = @id 

Quelque part dans la gâchette de mise à jour:

if exists (
select top 1 1 
from deleted d 
join inserted i on i.id = d.id 
where d.IsLocked = 1 and i.RowVersion <> d.RowVersion) 
begin 
print 'Row is locked' 
rollback tran 
end 
+0

J'ai essayé cela, mais je suis toujours capable de sélectionner des données et lorsque j'effectue une mise à jour, l'instruction attend jusqu'à ce que le verrou soit libéré, puis exécute la mise à jour. Ce n'est pas ce que je veux. Je veux informer l'utilisateur si un enregistrement est verrouillé. – Martijn

1

Sql Server a verrouillage des conseils, mais ceux-ci sont limités à la portée d'une requête.

Si la décision de verrouiller l'enregistrement est prise dans une application, vous pouvez utiliser les mêmes mécanismes que le verrouillage optimiste et refuser toute modification apportée à l'enregistrement par l'application.

Utilisez un horodatage ou un guid comme verrou sur l'enregistrement et refusez l'accès ou les modifications à l'enregistrement si la clé de verrouillage erronée est donnée. Attention à déverrouiller les enregistrements à nouveau ou vous obtiendrez des orphelins

+1

J'ai réfléchi à une telle approche, mais que se passe-t-il si l'application plante? Ou si le serveur tombe en panne. Comment débloquer l'enregistrement dans une telle situation? – Martijn

+0

Il n'y a pas de moyen facile, je pense. Faites en sorte que les verrous expirent en enregistrant une date à laquelle ils ont été verrouillés et utilisez un déclencheur ou un travail planifié pour nettoyer les verrous qui existent depuis trop longtemps. Ce que vous faites essentiellement, c'est un verrouillage pessimiste. voir aussi ceci: http://stackoverflow.com/questions/386162/pessimistic-lock-in-t-sql – stombeur

9

En supposant que c'est serveur MS SQL, vous voulez probablement UPDLOCK, éventuellement combiné avec ROWLOCK (Table hints). Je vais avoir du mal à trouver un article décent qui décrit la théorie, mais voici par exemple rapide:

SELECT id From mytable WITH (ROWLOCK, UPDLOCK) WHERE id = 1 

Cette déclaration placera une update lock sur la ligne pendant toute la durée de l'opération (il est donc important d'être conscient de quand la transaction se terminera). Comme les verrous de mise à jour sont incompatible with exclusive locks (requis pour mettre à jour les enregistrements), cela empêchera quiconque de mettre à jour cet enregistrement jusqu'à la fin de la transaction. Notez que les autres processus qui tentent de modifier cet enregistrement seront bloqués jusqu'à la fin de la transaction, mais continueront avec l'opération d'écriture demandée une fois la transaction terminée (à moins qu'ils ne soient expirés ou bloqués en tant que processus bloqués). Si vous souhaitez éviter cela, vos autres processus doivent utiliser des astuces supplémentaires pour soit abandonner si un verrou incompatible est détecté, soit ignorer l'enregistrement s'il a été modifié.


En outre, Vous ne devriez pas utiliser cette méthode pour bloquer des enregistrements en attendant l'entrée utilisateur. Si c'est votre intention, vous devriez ajouter une sorte de colonne "en cours de modification" à votre table. Les mécanismes de verrouillage du serveur SQL ne sont vraiment appropriés que pour préserver l'intégrité des données/éviter les interblocages - les transactions doivent généralement être maintenues aussi courtes que possible et ne doivent certainement pas être maintenues en attente de l'entrée de l'utilisateur.

+0

Lorsque j'utilise ceci, l'instruction de mise à jour attend que le verrou soit libéré, puis exécute une mise à jour. Je ne veux pas de ce comportement. Dès qu'un enregistrement est bloqué, l'utilisateur doit voir un message. En procédant ainsi, je ne peux pas avertir l'utilisateur car l'instruction de mise à jour attend que le verrou soit libéré. Je veux que l'instruction de mise à jour s'arrête et donne d'une manière ou d'une autre une erreur/exception/avertissement afin que je puisse avertir l'utilisateur. – Martijn

+0

@Martijn - Votre deuxième instruction de mise à jour doit être exécutée avec l'indicateur 'NOWAIT', ce qui le fera revenir dès qu'un verrou est rencontré plutôt que d'attendre le délai. – Justin

+0

L'instruction ne devrait-elle pas lire 'SELECT SELECT From mytable WITH (ROWLOCK, UPDLOCK) OERE id = 1'? – nash

0

Vous ne voulez pas attendre que le verrou soit libéré et afficher le message dès que vous rencontrez un verrou, si c'est le cas, alors vous avez essayé NOWAIT. Voir Table Hints (Transact-SQL) et SQL Server 2008 Table Hints pour plus de détails. Pour bénéficier de NOWAIT vous devez verrouiller les enregistrements sur les modifications, google pour plus de détails.

Questions connexes