我们有一个存储过程,用户可以手动运行该存储过程以获取全天不断使用的报表的一些更新编号。

我有第二个存储过程,应该在第一个存储过程运行之后运行它基于从第一个存储过程获得的数字,但是它需要更长的时间运行并且用于单独的进程,因此我不想让用户在第二个存储过程运行时等待。

是否可以让一个存储过程启动第二个存储过程,并立即返回而无需等待结果?

我正在使用SQL Server2005。

评论

如何调用存储过程? ASP.NET Web应用程序? SSRS?

您可以为此使用服务代理

@ Mr.Brownstone通常可以从ASP.Net Web应用程序中调用它,尽管其中一个以上可以调用它。我必须仔细检查。它有时也可以从SSRS手动运行。

@MartinSmith我过去曾与SQL Service Broker一起工作过,希望能有一种更简单的方法。看起来像这样的简单设置很复杂。

@MartinSmith几乎就是我的想法-另外,对于SSRS,您不能,但是您可以做的是将Report Viewer合并到应用程序中并将rdl移入应用程序-这样就可以进行异步调用以及报告。

#1 楼

看来有多种方法可以完成此操作,但是我发现最简单的方法是Martin建议在SQL作业中设置过程,并使用存储过程中的异步sp_start_job命令启动它。
EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'

这仅对我有用,因为我不需要为存储过程指定任何参数。
根据您的情况可能起作用的其他建议是


建议像Martin和Sebastian这样的SQL Service Broker。如果您不介意设置它并学习它的工作原理的复杂性,那么这可能是最好的建议。


在负责执行存储的代码中异步运行该过程
这不是一个坏主意,但是就我而言,存储过程是从多个地方调用的,因此找到所有这些地方并确保它们也调用第二个过程似乎并不实际。另外,第二个存储过程非常关键,忘记运行它可能会对我们公司造成一些重大问题。


使第一个存储过程设置一个标志,并设置一个循环作业来检查该标志并运行它(如Jimbo建议的)(如果已设置)。我不喜欢会持续运行并每隔几分钟检查一次更改的作业,但是根据您的情况,这当然是值得考虑的选择。



评论


查看使用Service Broker的现成示例的异步过程执行。与sp_job相比,优点是它可以在Express Edition上运行,并且完全包含在数据库中(不依赖于MSDB作业表)。后者对于DBM故障转移和HA / DR恢复非常重要。

–雷木斯·鲁萨努(Remus Rusanu)
13年2月18日在21:29

拍摄时,我看到Martin链接了同一篇文章。我将为故障转移/ DR参数保留注释。

–雷木斯·鲁萨努(Remus Rusanu)
13年2月18日在21:31

@RemusRusanu:好的,这是有关Service Broker的最佳信息来源之一,但是我想您已经知道了;-)。

–玛丽安
13年2月19日在18:07

我喜欢@Rusanu的链接,但我想要没有响应的东西(我认为与这个问题匹配)。我在abamacus.blogspot.com/2016/05/…写下了简化版

–算盘
16年5月11日在21:09

另外,如果尝试启动SQL Agent作业,它将失败,并且对对象'sp_start_job',数据库'msdb',架构'dbo'的EXECUTE权限被拒绝。此外,Azure上也不存在Service Broker或Sql Agent。我不知道为什么微软在经过十年半的询问后拒绝添加EXECUTE ASYNC RematerializeExpensiveCacheTable。

–伊恩·博伊德(Ian Boyd)
17年8月2日,14:47



#2 楼

您可以将服务代理与队列上的激活一起使用。这样,您可以将过程调用的参数发布到队列中。这大约需要插入的时间。提交事务并可能再等待几秒钟后,激活将自动异步调用接收程序。它不仅仅是wuold,还必须获取队列的参数并完成所需的工作。

#3 楼

这个老问题值得一个更全面的答案。其中一些在其他答案/评论中提到,某些可能对OP的特定情况有效,也可能不起作用,但对于希望从SQL异步调用存储的proc的其他情况可能有效。

完全明确:TSQL(本身)不具有异步启动其他TSQL操作的能力。

这并不意味着您仍然没有很多选择:



SQL Agent作业:创建多个SQL作业,然后安排它们在所需时间运行,或者使用sp_start_job从“主控”存储的proc中异步启动它们。如果您需要以编程方式监视其进度,只需确保每个作业都更新一个自定义的JOB_PROGRESS表即可(或者您可以使用Gregory A. Larsen的这篇出色文章中描述的未记录的函数xp_sqlagent_enum_jobs检查它们是否已经完成)。即使并行进程使用不同的参数运行相同的存储proc,也必须创建多个要运行的单独作业。

SSIS程序包:对于更复杂的异步方案,请创建具有以下内容的SSIS程序包:一个简单的分支任务流。 SSIS将在单个spid中启动这些任务,SQL将并行执行这些任务。从SQL代理作业中调用SSIS包。

自定义应用程序:使用该语言提供的异步方法,用您选择的语言(C#,Powershell等)编写一个简单的自定义应用程序。在每个应用程序线程上调用一个SQL存储的proc。

OLE自动化:在SQL中,使用sp_oacreatesp_oamethod来启动一个新的进程,以调用彼此存储的proc,如本文所述,Gregory A. Larsen也是如此。 。

Service Broker:研究使用Service Broker,这是本文中异步执行的一个很好的例子。

CLR并行执行:按照Alan Kaplan的本文中的说明使用CLR命令Parallel_AddSqlParallel_Execute(仅适用于SQL2005 +)。

计划的Windows任务:出于完整性考虑列出,但我不喜欢此选项。

如果是我,我可能会在较简单的方案中使用多个SQL Agent Job,而在较复杂的方案中使用SSIS软件包。

对于您来说,调用SQL Agent作业听起来像是一个简单且易于管理的选择。

最后一条评论:SQL已经尝试在可能的情况下并行化各个操作*。这意味着不能同时运行两个任务,而不能同时运行两个任务。仔细测试以查看它是否真的可以改善任何东西。

我们有一个开发人员创建了一个DTS程序包,以同时运行8个任务。不幸的是,它只是一个4 CPU服务器:)

*假定默认设置。可以通过更改服务器的“最大并行度”或“相似性掩码”,或使用MAXDOP查询提示来修改。

评论


嗨,布拉德。我必须相信您可以从一个SQL代理作业中启动多个SQL代理作业,并且它们(多个)将异步运行。我认为,在父级工作上成功的唯一标准是开始一项子工作。失败(我认为)只能通过查看子作业的历史来查看。

–user8591443
19年11月19日在18:40

@ user8591443您要描述的主作业必须使用SQL脚本,该脚本通过sp_start_job启动其他作业,正如我在第一个项目要点中所述(因为没有内置的作业步骤类型为“开始另一个作业”) 。但我认为您对个别工作状态没有掌握的正确看法。您必须分别查询失败/成功状态。

– BradC
19年11月19日在20:38

是的,主sql代理作业中的每个代理步骤(每个作业一个)将具有一个单独的t-sql exec sp_start_job。

–user8591443
19年11月21日在17:35

#4 楼

是的,一种方法:


当第一个存储过程完成时,它将插入一条记录,其中包含第二个存储过程运行所需的所有信息
第二个存储过程运行如下一项工作,每分钟或您决定什么时间
它检查插入的记录,进行处理并将该记录标记为完整


评论


这将存储过程的执行限制为您正在运行的作业的数量,如果您只希望一次由一个客户端调用此存储就可以了-而您可能有多个客户端同时调用同一过程。此外,客户如何知道工作已完成而无需反复轮询数据库以了解是否已设置标志?

–全球DBA
13年2月18日在14:16

@ Mr.Brownstone-作业可能在运行时处理多个由不同存储过程调用排队的未完成任务。该存储过程还可以调用sp_start_job来启动它,或者根据需要动态创建作业,以避免每分钟轮询一次,但是这种情况下的复杂性可能意味着它不会比服务代理简单。

–马丁·史密斯
13年2月18日在14:25



@MartinSmith实际上,我已经为第二个存储过程设置了作业,因为它曾经每晚运行一次,直到我们发现它与第一个过程的编号无法正确同步的问题。如果我从第一个存储过程开始该作业,它将异步运行并立即从SP返回吗?

–雷切尔
13年2月18日在14:40

@Rachel-是的sp_start_job立即返回。虽然不记得需要什么权限。

–马丁·史密斯
13年2月18日在14:41



如果您不想打开较大的安全漏洞,则从另一个过程/数据库开始作业是一个相当复杂的问题。 Erland Sommarskog上有一篇文章介绍了您需要组合使用的各种技术:sommarskog.se/grantperm.html但是,这里没有完整的解决方案。

–塞巴斯蒂安·梅因(Sebastian Meine)
13年2月18日在15:02



#5 楼

另一种可能性是使第一个存储过程在完成时写入审计表,并在审计表上放置触发器,以便在写入审计表时启动第二个存储过程。无需连续轮询,也不需要额外的SQL Server代理作业。

评论


在对审计表的插入完成之前,第一个存储过程不会返回,而在触发器完成执行之前(包括对第二个存储过程的调用),这不会发生

–马丁·史密斯
13年2月18日在21:26

我已经研究过使用触发器,但是触发器是与INSERT或UPDATE语句同步运行的,而不是异步运行的,因此Martin是正确的,第一个过程仍然会等到第二个过程完成返回。

–雷切尔
13年2月19日在12:50