Bas*_*que 5 sql-server locking limits
Microsoft SQL Server 通过sp-getapplock命令和相关命令提供任意应用程序定义的锁定机制。
键, or resource_name
,被指定为一个字符串,一个 varchar 255。但文档还提到键/名称是散列的。
所以这让我想知道:
我正在为特殊需求应用程序的许多表的行实施悲观锁定机制。作为我的应用锁键/名称,我计划使用一个代表每个表的数字与存储在每一行中的 ID 号相结合。示例键/名称可能类似于mydb_myschema_table0000000142_row0000241738
. 我可能一次有许多活动,所以我需要了解这些限制。
我没有看到官方文档回答您的问题,但是您可以自己做一些事情(首先在测试/开发服务器上!)。这是我发现的:
除非您希望使用大量并发锁,否则您可能不会遇到任何问题。在 SQL Server 2017 CTP2.1 上,我能够获得1MM concurrent locks
大约26 seconds
. 没有碰撞,这似乎使用~286MB of memory
.
在SQL Server文档指定为32位,最多2,147,483,647锁“只受记忆”为64位(我假设你正在使用)。
测试脚本
下面是一个脚本,它获取 1MM 锁并对经过的时间、消耗的内存、遇到的冲突进行基本监控。
BEGIN TRAN;
DECLARE @result INT,
@i INT = 1,
@locks_attempted INT = 1000000,
@locks_acquired INT,
@ts DATETIME2 = SYSDATETIME();
WHILE (@i <= @locks_attempted)
BEGIN
DECLARE @Resource NVARCHAR(255) =
'LongStringSoThatTheFirst32CharactersAreIdentical_' + CAST(@i AS VARCHAR)
EXEC @result = sp_getapplock @Resource = @Resource, @LockMode = 'Exclusive';
IF (@result <> 0) THROW 50000, 'Failed to acquire lock', 0
SET @i = @i + 1;
END
DECLARE @elapsed_ms INT = DATEDIFF(MILLISECOND, @ts, SYSDATETIME());
SELECT @locks_acquired = COUNT(*)
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
AND resource_type = 'APPLICATION';
-- Acquired 1000000 of 1000000 locks in 26351 milliseconds
RAISERROR('Acquired %i of %i locks in %i milliseconds', 0, 1,
@locks_acquired, @locks_attempted, @elapsed_ms);
-- ~286MB of memory for OBJECTSTORE_LOCK_MANAGER
SELECT *
FROM sys.dm_os_memory_clerks
WHERE type = 'OBJECTSTORE_LOCK_MANAGER';
ROLLBACK;
Run Code Online (Sandbox Code Playgroud)
碰撞呢?
我在任何试验中都没有观察到冲突,但根据sys.dm_tran_locks的文档,似乎使用了 32 位哈希。使用如此短的哈希值,碰撞的几率应该相当高(见下图)。但是,即使使用10MM concurrent locks
,我也没有实现碰撞。这可能表明哈希在底层更为复杂,并且 的resource_description
列sys.dm_tran_locks
仅显示哈希的前 32 位(类似于仅显示@Resource
参数的前 32 个字符的方式)。或者它可能表明我很幸运。
如果您打算使用此策略,您应该检查您的实际数据是否有任何冲突。如果你这样做,你可以尝试把独特的元素(例如schema_id
,object_id
和你的ROWID)在的开始@Resource
。(尚不完全清楚,但文档建议 的前 32 个字符@Resource
可能与哈希组合以唯一标识锁。)
(图片来自Preshing on Programming)
你为什么要这样做?
sp_getapplock
对于与 SQL Server 自己提供的行级锁定类型类似的东西,大量使用它似乎是不寻常的。我假设您已经仔细考虑过其他方法,但如果您还没有这样做,您可能需要考虑不涉及 sp_getapplock 的其他解决方案。