我正在使用一个相对复杂的系统,在这个系统中,静态表根据需要从多个数据源更新,因为动态加载数据需要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]问题是可以同时请求这些数据。如果用户A和用户B都在第一次更新完成之前调用dbo.Get_Data,则会发生死锁。
是否有一个好的方法或模式让第二次呼叫等待到第一次完成,然后继续其查找?
发布于 2019-12-13 16:03:05
是否有一个好的方法或模式让第二次呼叫等待到第一次完成,然后继续其查找?
一次只能运行一个会话的代码块的最简单方法是使用应用锁。您可以使用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;发布于 2019-12-19 22:44:07
简单的修复可以是WITH (NOLOCK):
SELECT * FROM [dbo].[StaticResults] WITH (NOLOCK)这意味着您不会被进程中的并发事务阻塞,即使锁在表上,进程也会读取表数据。结果可能是用户在该尝试中看不到更新的数据。只要它不是金融交易或商业关键交易,它就能达到目的。
https://dba.stackexchange.com/questions/255585
复制相似问题