确定锁升级的阈值

时间:2011-01-13 10:51:45

标签: sql sql-server sql-server-2005

我有一个包含大约250万条记录的表,并将更新大约700,000条记录,并希望更新这些记录,同时仍允许其他用户查看数据。我的更新语句如下所示:

UPDATE A WITH (UPDLOCK,ROWLOCK)
SET A.field = B.field
FROM Table_1 A
INNER JOIN Table2 B ON A.id = B.id WHERE A.field IS NULL
AND B.field IS NOT NULL

我想知道是否有任何方法可以解决sql server在什么时候升级更新语句上的锁(因为我不希望整个表被锁定)?

我没有运行服务器跟踪的权限来查看锁的应用方式,所以有没有其他方法可以知道锁将在什么时候升级以覆盖整个表?

谢谢!

3 个答案:

答案 0 :(得分:3)

According to BOL一旦语句在对象的单个实例上获得了5,000个行或页级锁,就会尝试升级锁。如果此尝试失败,因为另一个事务具有冲突锁定,那么它将在每次获取额外的1,250个锁之后再次尝试。

我不确定你是否真的可以将这些数字视为福音,或者是否还有一些细微之处(我想你总是可以在任意数量的锁上达到实例的内存限制)

答案 1 :(得分:3)

正如@Martin所说,5000是BOL给出的数字,但是我看到实际数字在生产中有所不同。

您有两种选择:

1)批量更新并尝试将批量大小保持在5000

以下

2)通过以下方式禁用锁定升级(因为):

这是一种可用于系统地确定阈值的方法。 (假设您拥有VIEW SERVER STATE权限)。

DECLARE @BatchSize int;
SET @BatchSize = <Vary this number until you see a table lock taken>;

BEGIN TRAN

UPDATE TOP(@BatchSize) A WITH (UPDLOCK,ROWLOCK)
SET A.field = B.field
FROM Table_1 A
INNER JOIN Table2 B ON A.id = B.id
WHERE A.field IS NULL
AND B.field IS NOT NULL


SELECT
    * 
FROM
    sys.dm_tran_locks
WHERE
    [request_session_id] = @@spid


ROLLBACK

答案 2 :(得分:2)

ROWLOCK提示不会阻止锁升级,它只是通知服务器它不应该采用初始锁定级别并从行开始。

然后可以将行锁提升为表锁。

要在更新期间使表数据可供读取,请使用SNAPSHOT事务隔离级别。