Kev*_*vin 3 sql-server deadlock stored-procedures update
我正在使用一个相对复杂的系统,其中根据需要从多个数据源更新静态表,因为动态加载数据需要 4-5 秒,我们更喜欢快速向用户显示结果。
过程:
IF ( SELECT [LastStaticUpdateEvent] < [LastSaveEvent]
FROM [dbo].[Events]
WHERE [OrderNumber] = @OrderNumber
)
BEGIN
-- Update Static table
UPDATE [Static]
SET [Static].[A] = [App].[A]
,[Static].[B] = [App].[B]
FROM [dbo].[AppData] AS [App] -- View with many joins (4-5 secs)
INNER JOIN [dbo].[StaticResuts] AS [Static]
ON [Static].[OrderNumber] = [App].[OrderNumber]
WHERE [App].[OrderNumber] = @OrderNumber
-- Update Event Log
UPDATE [dbo].[Events]
SET [LastStaticUpdateVent] = SYSDATETIME()
WHERE [OrderNumber] = @OrderNumber
END
SELECT * FROM [dbo].[StaticResults]
Run Code Online (Sandbox Code Playgroud)
问题是可以同时请求这些数据。如果用户 A 和用户 B 在第一次 UPDATE 完成之前都调用了 dbo.Get_Data,则会发生死锁。
是否有一种好的方法或模式可以让第二次调用等到第一次调用完成后再继续查找?
是否有一种好的方法或模式可以让第二次调用等到第一次调用完成后再继续查找?
拥有一次只能由一个会话运行的代码块的最简单方法是使用Application Lock。您可以使用 SQL Server 的锁定引擎,但不是锁定特定的行、页或表,而是使用自定义名称创建锁定。例如
begin transaction;
--begin exclusive section
exec sp_getapplock @Resource = 'Get_Data Exclusive Lock', @LockMode = 'Exclusive';
--do stuff in only one session
--end exclusive section
exec sp_releaseapplock @Resource = 'Get_Data Exclusive Lock';
commit transaction;
Run Code Online (Sandbox Code Playgroud)