sql - 在更新记录时锁定记录的最佳方法是什么?

标签 sql sql-server database

如果我需要根据存储过程中相对复杂的WHERE子句从表列(恰好是主键列)中SELECT一个值,并且然后我想在没有任何其他并发存储过程 SELECTing 相同记录的情况下更新该记录,它是否像使用事务一样简单?还是我还需要将隔离提高到可重复读取?

看起来像这样:

Alter Procedure Blah
As
Declare @targetval int
update table1 set field9 = 1, @targetval = field1 where field1 = (
SELECT TOP 1 field1
FROM table1 t
WHERE
(t.field2 = 'this') AND (t.field3 = 'that') AND (t.field4 = 'yep') AND (t.field9 <> 1))
return

然后我在我的程序中获取我的 targetval,这样我就可以对其进行处理,同时我不必担心其他工作线程获取相同的 targetval。

我在这里说的是 SQL 2000、SQL 2005 和 SQL 2008。

最佳答案

ROWLOCK,UPDLOCK 添加到子查询中应该可以做到这一点。

ALTER PROCEDURE Blah
AS
  DECLARE @targetval INT

  UPDATE table1
  SET    field9 = 1,
         @targetval = field1
  WHERE  field1 = (SELECT TOP 1 field1
                   FROM   table1 t WITH (rowlock, updlock)
                   WHERE  ( t.field2 = 'this' )
                          AND ( t.field3 = 'that' )
                          AND ( t.field4 = 'yep' )
                          AND ( t.field9 <> 1 ))

  RETURN  

已更新

目前接受的这个问题的答案不使用updlock。我完全不相信这会奏效。据我在这种类型的带有子查询的查询测试中所见,SQL Server 只会为子查询获取 S 锁。然而,有时子查询会被优化掉,所以这种方法可能看起来像查询 2 中那样工作。

测试脚本 - 设置

CREATE TABLE test_table
(
id int identity(1,1) primary key,
col char(40)
)

INSERT INTO test_table
SELECT NEWID() FROM sys.objects

查询 1

update test_table
set col=NEWID()
where id=(SELECT top (1) id from test_table )

Plan for id query Trace for id query

查询2

update test_table
set col=NEWID()
where id=(SELECT max(id) from test_table)

Plan for max query Trace for max query

关于sql - 在更新记录时锁定记录的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4595643/

相关文章:

sql-server - 在 SQL Server 中重命名表后验证所有对象

database - 表示值可以是任何类型的键/值对(在关系数据库中)

php - 获取 MYSQL 中非数字 ID 的上一条和下一条记录

mysql - 将 MySQL 中的 CHAR 列转换为 DATETIME 列

sql - 公共(public)列名称不同时如何自然连接?

sql - 更新 SQL Server XML 列中的 XML 属性

sql - 在 Oracle 中为 varchar2 字段创建序列

mysql - 在 MySQL 查询中将时间戳转换为日期

sql - 使用 LIKE 查找 'exact' 匹配项

sql - SQL Server 中的不精确列是什么?