我想要锁定一条记录,然后没有人可以对该记录进行更改。当我释放锁定时,人们可能会更改记录。
在此期间,记录被锁定,我想向用户显示记录已被锁定并且不允许更改的警告。
我该怎么做?
我已经尝试了所有的IsolationLevel级别,但它们都没有我想要的行为。某些隔离级别会等到锁定释放后再进行更改。我不希望这样,因为在锁定记录时不允许更新。
如何锁定记录并拒绝所有更改?
我使用SQL Server 2008
答案 0 :(得分:9)
假设这是MS SQL服务器,您可能需要UPDLOCK
,可能还需要ROWLOCK
(Table 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
的好处,您需要锁定编辑记录,谷歌了解更多详情。