SQL存储过程超时

时间:2018-07-31 14:30:48

标签: sql sql-server windows stored-procedures service

我有一个存储过程,当通过.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

2 个答案:

答案 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)