gpt4 book ai didi

sql-server - sp_getapplock 同步对内存表的并发访问

转载 作者:行者123 更新时间:2023-12-02 08:36:40 28 4
gpt4 key购买 nike

我有大约 20 个相互消耗的存储过程,形成了一个树状依赖链。

然而,存储过程使用内存中的表进行缓存,并且可以从许多不同的客户端同时调用。

为了防止针对内存表的并发更新/删除尝试,我使用了 sp_getapplock 和 SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT ON;

我正在使用每个存储过程唯一的存储过程参数散列,但是对具有相同参数的同一存储过程的多个并发调用应该生成相同的散列。正是这种对具有相同参数的相同存储过程的并发调用的哈希值相等,为我提供了一个有用的资源名称来获取我们的应用锁。

下面是一个例子:

BEGIN TRANSACTION

EXEC @LOCK_STATUS = sp_getapplock @Resource= [SOME_HASH_OF_PARAMETERS_TO_THE_SP], @LockMode = 'Exclusive';

...some stored proc code...

IF FAILURE
BEGIN
ROLLBACK;
THROW [SOME_ERROR_NUMBER]
END

...some stored proc code...

COMMIT TRANSACTION

尽管将所有内容都包装在应该阻止任何并发更新或删除的应用锁中,但我仍然收到错误 41302:

The current transaction attempted to update a record that has been updated since this transaction started. The transaction was aborted. Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.

我是否错误地使用了 sp_getapplock?看来我建议的方法应该可行。

最佳答案

当您使用内存优化表开始您的事务时,您会得到您的“快照”,它基于事务开始的时间,用于乐观并发解决方案。不幸的是,您的锁在拍摄快照后就位,因此仍然完全有可能出现乐观并发解析失败。

考虑一下需要同一个锁的 2 个事务同时开始的情况。在获得锁或修改任何行之前,它们都“同时”开始它们的事务。它们的快照看起来完全一样,因为尚未修改任何数据。接下来,一个事务获得锁并继续进行更改,而另一个被阻塞。这个事务提交很好,因为它是第一个,所以它引用的快照仍然与内存中的数据匹配。另一个事务现在获得了锁,但是它的快照是无效的(但是它还不知道这一点)。它继续执行并在最后意识到它的快照是无效的,所以它会抛出一个错误。事实上,事务甚至不需要几乎同时开始,第二个事务只需要在第一个提交之前开始。

您需要在应用程序级别强制执行锁定,或者通过在 session 级别使用 sp_getapplock。

希望这对您有所帮助。

关于sql-server - sp_getapplock 同步对内存表的并发访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20654472/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com