我有一个存储过程,当通过.net Windows服务调用时,该过程将超时。
错误:执行超时已过期。
在操作完成之前已经过了超时时间,或者服务器没有响应。等待操作超时
@fetchbatchsize从ctp_config获取值为“ 2500”的值,并使用该值从另一个表ctp_otran中选择前2500条记录。 ctp_otran中的大约记录为23102025。
同一存储过程可以很好地处理'1000'记录,而不会出现任何超时问题。
以下是存储的过程。
ALTER PROCEDURE [dbo].[sp_ctp_get_otran]
@feed varchar(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @fetchbatchsize char(25),
@parameter varchar(50) = 'otran_default_batch_size_'
,@dync_exec nvarchar(MAX)
set @fetchbatchsize = (select value from [dbo].[ctp_config] where parameter =
@parameter+@feed)
If(@fetchbatchsize is null)
set @fetchbatchsize = '1000'
select top (0) ctp_otran.otran_id, ctp_otran.unq_number as unq_number,
ctp_otran.entity, ctp_otran.field,
ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value,
ctp_otran.proc_status
into #otran
from ctp_otran with (nolock)
select @dync_exec = 'INSERT INTO #otran (
otran_id,
unq_number,
entity,
field,
str_value,
dec_value,dtm_value,proc_status
)
select top (cast(' +@fetchbatchsize+ ' as int)) ctp_otran.otran_id,
ctp_otran.unq_number as unq_number,
ctp_otran.entity, ctp_otran.field,
ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value,
ctp_otran.proc_status
from ctp_otran with (nolock)
where ctp_otran.feed = '''+@feed + '''
and ctp_otran.proc_status = 0
order by entity, unq_number, field;'
EXEC (@dync_exec)
update ctp_otran
set proc_status = 3 -- in process
where otran_id in (select otran_id from #otran);
select otran_id, unq_number, entity, field, str_value, dec_value, dtm_value,
proc_status
from #otran;
drop table #otran;
END
答案 0 :(得分:0)
假设您使用的是SQL 2005或更高版本(并且确实是 ),则可以用以下方式替换动态SQL:
INSERT INTO #otran (
otran_id,
unq_number,
entity,
field,
str_value,
dec_value,dtm_value,proc_status
)
select top (@fetchbatchsize)
ctp_otran.otran_id,
ctp_otran.unq_number as unq_number,
ctp_otran.entity, ctp_otran.field,
ctp_otran.str_value, ctp_otran.dec_value, ctp_otran.dtm_value,
ctp_otran.proc_status
from ctp_otran with (nolock)
where ctp_otran.feed = @feed
and ctp_otran.proc_status = 0
order by entity, unq_number, field;
@fetchbatchsize当然需要存储为Int而不是Varchar。
最后,您不需要显式删除临时表。当存储过程结束时,它们消失了。
答案 1 :(得分:0)
我认为您可以将整个逻辑替换为:
select @fetchbatchsize = value
from dbo.ctp_config
where parameter = @parameter+@feed
update o
set proc_status = 3 -- in process
from (
select top @fetchbatchsize *
from ctp_otran
where ctp_otran.feed = @feed
and ctp_otran.proc_status = 0
order by entity, unq_number, field
) o
output inserted.otran_id, inserted.unq_number, inserted.entity, inserted.field, inserted.str_value, inserted.dec_value, inserted.dtm_value, inserted.proc_status
没有测试这个,但是不知道为什么它不起作用。如果派生表不起作用,则CTE至少应该如此。
如果您有多个进程同时在表中进行相同的处理,那么您的代码将在两种竞态条件下结束,在竞态条件下,多次选择相同的ID并导致数据库死锁(这可能就是为什么您添加了nolock)