我有一个用于表单处理的.Net应用程序,可以删除/更新/插入三个不同的SQL Server 2012数据库中的数据。当应用程序运行时,它会打开一个数据上下文,然后在该上下文中为每个需要处理的表单打开一个事务(这会每分钟运行一次,因此通常一次只能运行一个表单)。在这个事务中发生了一堆事情 - 包括多个存储过程调用。
所以这就是问题所在:
我们设置的服务器与我所说的是完全相同的规格(虽然我可疑:))。一个用于开发工作;另一个用于客户端测试。在我们的开发环境中,处理运行没有问题;但在客户端测试网站上,它每次都会挂起。而我正在试着确定原因。
在以下TSQL代码中,插入Param表失败。除列名外,Param表与Method表基本相同。两个插入都具有与Form表类似的外键关系,并且都将int值插入到ID列中。
当我运行SQL Server Profiler时,我被告知FormDB上有一个不允许插入的锁。但是,我可以更改Param插入的select语句,它可以工作。我已经通过以下方式进行了更改,所有这些方式都“起作用”,因为它们不会导致阻塞问题:
我觉得我正在失去理智,因为我无法理解为什么它不起作用。当组合的select语句中有三个东西 - @ newKey,ParamID和from语句时,插入似乎只会失败。
我确保每个sproc都有SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED并在必要时使用nolock。
为什么我可以通过上面的三个场景成功插入Param表,但是后面的代码中的Param插入失败了?为什么我在探查器中没有收到相同的锁定消息?此过程中大约有5个其他插入符合相同的模式。所有这些都没有问题。
有什么想法吗?感谢。
USE [PROD]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[HELPSPROC]
@oldKey int
AS
BEGIN
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
declare @newKey int
, @spKey int
, @modifyDate datetime = getdate()
, @modifyUser varchar(30) = 'User'
/*
a bunch of stuff happens here, including setting the @spKey value.
this all happening correctly -- we have a valid integer value when we go into the next part
*/
---------------FORM---------------
INSERT INTO FormDB.dbo.Form
(formtype, formstatus, modifydate, modifyuser)
Select
'TestFormType', 'DRAFT', @modifyDate, @modifyUser
From FormDB2.dbo.Form f
Where f.Pkey = @oldKey
--grab the new int identifier -- works
set @newKey = (select scope_identity())
/*
stuff happens here. all is good in this part
*/
---------------Param---------------
INSERT INTO FormDB.dbo.Param
(FormKey, ParamID, ModifyDate, ModifyUser)
select @newKey, p.ParamID, @modifyDate, @modifyUser
from PROD.dbo.Table1 apd
inner join PROD.dbo.ParameterTable p
on apd.TableTwoKey = p.TableTwoKey
where apd.PKey = @spKey
---------------Method---------------
INSERT INTO FormDB.dbo.Method
(FormKey, MethodID, ModifyDate, ModifyUser)
select @newKey, r.MethodID, @modifyDate, @modifyUser
from PROD.dbo.Table1 apd
inner join PROD.dbo.MethodTable r
on apd.TableTwoKey = r.TableTwoKey
where apd.PKey = @spKey
/*
one more insert ...
*/
RETURN 1
END
GO
答案 0 :(得分:0)
我仍然不明白为什么这个问题,但我找到了解决方案。
此进程的vb.net代码中发生了很多事情:跨三个独立数据库的多个linq-to-sql插入/删除/更新,以及两个单独的存储过程调用。为了增加这种混淆,为每个数据库声明了单独的上下文,每个上下文都有自己的事务。简而言之,一堆活动部件。
第二个存储过程调用是有条件的,基于处理表单的某些值。我只是从vb.net代码中取出了那个调用,并将条件逻辑和存储过程调用放在第一个proc中。这解决了它。第二个存储过程直接在第一个之后调用 - 待决条件 - 所以一切都很好。
问题解决了 - 但如果有人能解释为什么会这样,我将不胜感激。谢谢!