如何执行行锁?

时间:2010-09-22 07:58:30

标签: c# sql sql-server-2008 locking

我想要锁定一条记录,然后没有人可以对该记录进行更改。当我释放锁定时,人们可能会更改记录。

在此期间,记录被锁定,我想向用户显示记录已被锁定并且不允许更改的警告。

我该怎么做?

我已经尝试了所有的IsolationLevel级别,但它们都没有我想要的行为。某些隔离级别会等到锁定释放后再进行更改。我不希望这样,因为在锁定记录时不允许更新。

如何锁定记录并拒绝所有更改?

我使用SQL Server 2008

4 个答案:

答案 0 :(得分:9)

假设这是MS SQL服务器,您可能需要UPDLOCK,可能还需要ROWLOCKTable hints)。我很难找到一篇描述理论的体面文章,但这里有一个简单的例子:

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

此语句将在事务持续时间内在行上放置update lock(因此了解事务何时结束非常重要)。由于更新锁是incompatible with exclusive locks(更新记录所需),这将阻止任何人在事务结束之前更新此记录。

请注意,尝试修改此记录的其他进程将被阻塞,直到事务完成,但是在事务结束后将继续执行它们请求的任何写入操作(除非它们作为死锁进程超时或终止)。如果您希望阻止这种情况,那么您的其他进程需要使用其他提示,以便在检测到不兼容的锁时中止,或者如果记录已更改则跳过该记录。


此外,您不应在等待用户输入时使用此方法锁定记录。如果这是您的意图,那么您应该在表中添加某种“被修改”列。

SQL服务器锁定机制实际上仅适用于保持数据完整性/防止死锁 - 事务通常应保持尽可能短,并且在等待用户输入时肯定不能维护。

答案 1 :(得分:1)

Sql Server具有锁定提示,但这些提示仅限于查询范围。

如果在应用程序中决定锁定记录,则可以使用与乐观锁定相同的机制,并拒绝对应用程序中的记录进行任何更改。

使用时间戳或guid作为记录的锁定,如果给出了错误的锁定键,则拒绝访问或更改记录。小心再次解锁记录,否则你会得到孤儿

答案 2 :(得分:0)

在SO上查看此duplicate question

基本上是:

begin tran

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

--Here goes your stuff

commit tran

归档

这样的事可能吗?

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

更新触发器中的某处:

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

答案 3 :(得分:0)

您不想等待锁定被释放并在遇到锁定时立即显示消息,如果是这种情况,那么您是否尝试NOWAIT。有关详细信息,请参阅Table Hints (Transact-SQL)SQL Server 2008 Table Hints。为了获得NOWAIT的好处,您需要锁定编辑记录,谷歌了解更多详情。