我试图了解我们在 SQL Server 2000 中遇到的一个问题。我们是一个中等事务性的网站,我们有一个名为的存储过程sp_GetCurrentTransactions
,它接受一个客户ID和两个日期。
现在,根据日期和客户,此查询可以返回从零到 1000 行的任何内容。
问题:我们所经历的是,Execution Timeout Expired
当特定客户端尝试执行该存储过程时,我们会突然收到许多错误(通常或类似的错误)。所以我们检查了查询,在 SSMS 中运行它,发现它需要 30 秒。所以我们重新编译存储的 proc 并且 -bang- 它现在在 300 毫秒内运行。
我已经和我们的 DBA 谈过了。他告诉我,当我们创建存储过程时,数据库创建了一个查询计划。他说对于那组参数是一个很好的计划,但是如果你向它抛出一组特定的参数,那么该计划将不是该数据的最佳计划,因此你会看到它运行缓慢。
提供给我的选项是将问题查询从存储过程移回动态 SQL,在每次运行时都会创建执行计划。
这对我来说就像是后退了一步,我觉得必须有办法解决这个问题。有没有其他方法来处理这个问题?
任何和所有的回应表示赞赏。
我们运行 SQL Server 2000,每天晚上都会遇到一些这样的错误。
Could not continue scan with NOLOCK due to data movement
Run Code Online (Sandbox Code Playgroud)
引发此错误的查询是一个大型复杂查询,它连接了十多个表。我们的基础数据可以经常更新。
文化“最佳实践”是,在过去,NOLOCK
提示的引入提高了性能并改进了并发性。这个查询不需要 100% 准确,即我们会容忍脏读等。然而,我们正在努力理解为什么数据库会抛出这个错误,即使我们有所有这些锁定提示。
任何人都可以对此有所了解 - 温柔一点,我实际上是一名程序员,而不是 DBA :)
PS:我们已经应用了前面提到的修复:http : //support.microsoft.com/kb/815008
我们使用的是 SQL Server 2000。
我想知道如果我们NOLOCK
在READ COMMITTED
事务块中使用提示会有什么风险,例如:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
BEGIN TRANSACTION
IF EXISTS(SELECT * FROM clients (NOLOCK) WHERE clientID = 23249)
BEGIN
PRINT 'TODO Update client'
END
ELSE
BEGIN
PRINT 'TODO Insert client'
END
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
我担心的是,尽管事务块具有隔离级别,但 NOLOCK 提示将允许进行 ditry 读取。
这可能吗?
PS:我知道关于为什么我首先使用锁定提示存在争议,但我只想知道这种情况下的风险是什么。