异步调用存储
起源
因为项目中,需要用到存储过程进行大量的计算,存储过程执行的速度让人感觉揪心,不能说让客户在页面上待个几分钟吧,因此就想,有没有一种方法,可以做到客户发出请求,然后数据库在后台执行任务,于是.......
具体方法
经过百度知道,作业可以在后台自动执行一段存储过程,所以,通过动态生成作业,然后作业再调用存储过程就好了,动态生成作业就需要到存储过程的帮助,通过设置好一些参数后,生成一个临时作业,然后设置作业立即执行就可以了,下面是生成动态作业的代码,这个存储过程是在网上找的,但是自己也有改过一些代码,满足我们自己的项目需求
1 set ANSI_NULLS ON 2 set QUOTED_IDENTIFIER ON 3 GO 4 /****************************************************************************** 5 * 在SQL SERVER 中创建用于执行异步调用的临时Job 6 * @EXECSQL: 填写要执行的存储过程的名称,或者是sql语句 7 ******************************************************************************/ 8 ALTER Procedure [dbo].[AsyRunPro] 9 @EXECSQL nvarchar(4000)='EXEC dbo.BatchRatingAsy ', 10 @job nvarchar(50)='JL_AsynchronousInvoking', 11 @servern nvarchar(50)=N'(local)' , 12 @dbname nvarchar(50)=''--下面会通过db_name()函数获取 13 AS 14 15 BEGIN TRANSACTION 16 DECLARE @JobID BINARY(16) 17 DECLARE @ReturnCode INT 18 SELECT @ReturnCode = 0 19 20 BEGIN 21 SET @dbname=CONVERT(NVARCHAR(50),db_name()) 22 --SELECT @dbname 23 -- Add the job 24 EXECUTE @ReturnCode = msdb.dbo.sp_add_job @job_id = @JobID OUTPUT , 25 @job_name = @job, 26 @owner_login_name = N'', 27 @description = N'AsynchronousInvokingRating', -- the description of the job 28 @category_name = N'[Uncategorized (Local)]', 29 @enabled = 1, 30 @notify_level_email = 0, 31 @notify_level_page = 0, 32 @notify_level_netsend = 0, 33 @notify_level_eventlog = 0, 34 @delete_level= 3 35 36 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 37 38 -- Add the job steps 39 EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep @job_id = @JobID, 40 @step_id = 1, 41 @step_name = N'step1', 42 @command = @EXECSQL, -- sql batch 43 @database_name = @dbname, --作业所操作的数据库的名字 44 @server = N'', 45 @database_user_name = N'', 46 @subsystem = N'TSQL', 47 @cmdexec_success_code = 0, 48 @flags = 0, 49 @retry_attempts = 0, --只是执行一次 50 @retry_interval = 0, 51 @output_file_name = N'', 52 @on_success_step_id = 0, 53 @on_success_action = 1, -- 成功则删除 54 @on_fail_step_id = 0, 55 @on_fail_action = 2 -- on fail abort 56 --select @JobID 57 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 58 59 --set the star step id of the job 60 EXECUTE @ReturnCode = msdb.dbo.sp_update_job @job_id = @JobID, 61 @start_step_id = 1 62 63 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 64 65 -- Add the Target Servers 66 EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, 67 @server_name = @servern--传入的服务器名称 68 69 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 70 71 END 72 73 COMMIT TRANSACTION 74 GOTO EndSave 75 76 QuitWithRollback: 77 IF (@@TRANCOUNT > 0) BEGIN 78 ROLLBACK TRANSACTION 79 RETURN 1 80 END 81 EndSave: 82 83 --立刻开启作业 84 EXEC @ReturnCode = msdb.dbo.sp_start_job @job_id = @JobID 85 86 --返回响应调用者 87 RETURN @ReturnCode
上面写出一些主要的参数的注释,对于具体创建作业可以到 http://msdn.microsoft.com/zh-cn/library/ms187880.aspx 去了解,这里就不再继续说了
注意事项
其中要注意的是,作业的执行需要Agent服务的支持所以在SQL SERVER Configuration Manager 开启 SQL SERVER AGENT 服务,如果项目是一直需要用到的话,最好设置为自动开启,因为如果因为Agent服务未能成功开启的话,作业就不会被自动删除,那就意味着,下次如果是创建同名的作业的话,就无法创建成功!所以,最好要考虑万一作业未能删除,就要怎么办,而我自己的作法是不创建重名的作业~~~
总结
当然异步调用有好也有不好,好的就是让客户感觉到"速度",但是真正来说,存储过程并未能完全执行完毕,也不知道何时执行完毕,当然也可以再做一个功能去检查存储过程何时执行完毕~~

浙公网安备 33010602011771号