我们有一个存储过程,用户可以手动运行该存储过程以获取全天不断使用的报告的一些更新编号。
我有第二个存储过程,应该在第一个存储过程运行之后运行,因为它基于从该第一个存储过程获得的数字,但是它需要更长的时间运行并且用于单独的过程,所以我不想让用户等待第二个存储过程运行。
有没有一种方法可以让一个存储过程启动另一个存储过程,然后立即返回而无需等待结果?
我正在使用SQL Server 2005。
我们有一个存储过程,用户可以手动运行该存储过程以获取全天不断使用的报告的一些更新编号。
我有第二个存储过程,应该在第一个存储过程运行之后运行,因为它基于从该第一个存储过程获得的数字,但是它需要更长的时间运行并且用于单独的过程,所以我不想让用户等待第二个存储过程运行。
有没有一种方法可以让一个存储过程启动另一个存储过程,然后立即返回而无需等待结果?
我正在使用SQL Server 2005。
Answers:
看起来有多种方法可以完成此操作,但是我发现最简单的方法是Martin建议在SQL作业中设置过程,并使用存储过程中的异步sp_start_job命令启动它。
EXEC msdb.dbo.sp_start_job @job_name='Run2ndStoredProcedure'
这仅对我有用,因为我不需要为存储过程指定任何参数。
根据您的情况,其他可行的建议是
在负责执行存储过程的代码中异步运行流程,如Mr.Brownstone建议。
这不是一个坏主意,但是在我的案例中,从多个地方调用了存储过程,因此找到所有这些地方并确保它们也调用第二个过程似乎并不实际。同样,第二个存储过程也很关键,而忘记运行它可能会对我们公司造成一些重大问题。
EXECUTE permission was denied on the object 'sp_start_job', database 'msdb', schema 'dbo'.
并且Azure上也不存在Service Broker或Sql Agent。我不知道为什么微软在经过十年半的询问后拒绝添加EXECUTE ASYNC RematerializeExpensiveCacheTable
。
您可以将服务代理与队列上的激活一起使用。这样,您可以将过程调用的参数发布到队列中。这大约需要插入的时间。提交事务并可能再等待几秒钟后,激活将自动异步调用接收程序。它不仅仅是wuold,还必须获取队列的参数并完成所需的工作。
这个老问题值得一个更全面的答案。其中一些在此处的其他答案/注释中提到,另一些可能适用于OP的特定情况,也可能不适用,但可能适用于希望从SQL异步调用存储的proc的其他情况。
只是为了完全明确:TSQL确实不(本身)具有异步启动其他TSQL操作的能力。
这并不意味着您仍然没有很多选择:
sp_start_job
。如果您需要以编程方式监视其进度,只需确保每个作业都更新一个自定义的JOB_PROGRESS表即可(或者您可以xp_sqlagent_enum_jobs
按照Gregory A. Larsen的这篇出色文章中的说明,检查它们是否已经使用了未记录的功能)。即使并行进程运行的是具有不同参数的相同存储过程,您也需要创建尽可能多的独立作业,以使并行进程运行。sp_oacreate
并sp_oamethod
启动一个新进程,以互相调用存储的proc,如本文所述,Gregory A. Larsen也是如此。Parallel_AddSql
,Parallel_Execute
如Alan Kaplan 在本文中所述(仅适用于SQL2005 +)。如果是我,那么我可能会在较简单的方案中使用多个SQL Agent Job,在较复杂的方案中使用SSIS软件包。
就您而言,调用SQL Agent作业听起来像是一个简单且易于管理的选择。
最后一条评论:SQL已经尽可能尝试并行化各个操作*。这意味着不能同时运行两个任务,而不能同时运行两个任务。仔细测试以查看它是否真的可以改善任何东西。
我们有一个开发人员创建了一个DTS包,以同时运行8个任务。不幸的是,它只是一个4-CPU服务器:)
*假设为默认设置。可以通过更改服务器的“最大并行度”或“相似性掩码”或使用MAXDOP查询提示来修改此设置。
是的,一种方法:
sp_start_job
以启动它,或者根据需要动态创建作业,以避免每分钟轮询一次,但是这种情况下的复杂性可能意味着它不会比服务代理简单。
sp_start_job
立即返回。虽然不记得需要什么权限。
另一种可能性是,当第一个存储过程完成时将其写入审计表,并在写入审计表时将触发器置于审计表上,以启动第二个存储过程。无需连续轮询,也不需要额外的SQL Server代理作业。
INSERT
or UPDATE
语句同步运行,而不是异步运行,因此Martin是正确的,第一个过程仍然会一直等到第二个过程完成返回。