.net 存储过程偶尔执行两次
我创建了一个.net控制台应用程序,它从计算机和/或用户收集一些基本的库存信息。它通过存储过程将此信息转储到SQL Server 2012数据库中 我偶尔会在至少两个表中出现重复记录 存储过程非常简单,当存储过程接收到序列号(以及其他参数)时,它会在资产表中搜索序列号。如果找到匹配项,则返回.net 存储过程偶尔执行两次,.net,sql-server,stored-procedures,.net,Sql Server,Stored Procedures,我创建了一个.net控制台应用程序,它从计算机和/或用户收集一些基本的库存信息。它通过存储过程将此信息转储到SQL Server 2012数据库中 我偶尔会在至少两个表中出现重复记录 存储过程非常简单,当存储过程接收到序列号(以及其他参数)时,它会在资产表中搜索序列号。如果找到匹配项,则返回assetId,否则将创建新条目并返回新创建的assetId。同样在该过程中,使用先前返回的assetId将日期时间条目添加到事件表中 我开始看到的是资产表中的两条记录,它们具有顺序编号,但序列号相同。有趣的
assetId
,否则将创建新条目并返回新创建的assetId
。同样在该过程中,使用先前返回的assetId
将日期时间条目添加到事件表中
我开始看到的是资产表中的两条记录,它们具有顺序编号,但序列号相同。有趣的是,事件表中将有两条记录,分别对应于具有完全相同的日期时间的assetId
在我们拥有的22000多台计算机中,这只发生在五个序列号上,所以对我来说,这不是世界末日。然而,由于这个问题,我一直在质疑其余数据的可靠性
你知道这是怎么发生的吗
存储过程
--Create an asset row if there is not one and retrieve the id. Or just retrieve the id.
If (select count(assetid) from asset where serial=@serial) > 0
Begin
set @assetid = (select top 1 assetid from asset where serial=@serial )
End
Else
--Add asset to table
Begin
Insert into asset (serial, model, manufacturer)
values (@serial, @model, @manufacturer);
set @assetid = (Select SCOPE_IDENTITY())
End
--End Asset entry
--Insert Audit Event record
Insert into auditevent (assetid, audittime, username, computername, operatingsystem)
values (@assetid, @audittime, @username, @computername, @operatingsystem)
Declare @auditeventid int = (select SCOPE_IDENTITY())
--Send the ipString to the function that will convert it to a table and insert into IP Table
Insert into ipaddress (auditeventid, ipaddress)
select *
from CsvToTable(@auditeventid, @ipaddressvalues)
控制台应用程序(单线程)
如果不查看控制台应用程序的代码及其运行细节,就很难诊断此问题。例如,您是否可以运行多个实例并让两个线程尝试同时执行同一任务 当有库存项目要添加时,您可以通过运行控制台应用程序两次来测试这是否是原因,并查看它是否重复 存储过程的逻辑似乎很好,但我会重新编写它:
IF EXISTS (SELECT 1 FROM asset WHERE serial=@serial)
-- Create an asset row if it doesn't exist
BEGIN
SELECT @assetid = assetid FROM asset WHERE serial=@serial
END
ELSE
--Add asset to table
BEGIN
INSERT INTO asset (serial,model,manufacturer)
VALUES (@serial,@model,@manufacturer);
SELECT @assetid = SCOPE_IDENTITY()
END
这是未经测试的,但您应该明白。为什么要从应用程序进行审核,这是一个数据库反模式?我建议将
asset.assetid
作为主键,以避免重复,即使在其他地方有bug。我还建议用begintransaction
/commit
包装所有语句。顺便说一句,我认为问题在于调用存储过程的控制台应用程序,或者控制台应用程序是如何触发执行的。@HLGEM我不知道有任何其他方法可以快速完成任务。我考虑了一个服务器驱动的模型,但需要更多的代码和调试,这意味着时间。什么是更好的模型?@wdosanjos asset.assetid实际上是PK。我认为重复的记录实际上是不同的,因为assetid字段增加了1。请参阅上面我添加的控制台代码。这是一个非常简单的程序。它是单线程的,所以没有运行任何函数两次。它从WMI收集数据,存储到变量,并通过存储过程保存到db。
IF EXISTS (SELECT 1 FROM asset WHERE serial=@serial)
-- Create an asset row if it doesn't exist
BEGIN
SELECT @assetid = assetid FROM asset WHERE serial=@serial
END
ELSE
--Add asset to table
BEGIN
INSERT INTO asset (serial,model,manufacturer)
VALUES (@serial,@model,@manufacturer);
SELECT @assetid = SCOPE_IDENTITY()
END