MSSMS 2012用户取消操作无法触发TRY CATCH捕获求助
问题描述
在MSSMS 2012中执行SQL脚本时,若用户手动取消操作,原本用于记录错误事件的TRY CATCH块并未触发,自定义日志表的更新语句从未执行,预期写入的错误号45188和错误文本"The operation has been cancelled by user."均为NULL。
当前使用的代码如下:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET NOCOUNT ON; SET XACT_ABORT ON; SET ANSI_WARNINGS OFF BEGIN TRY --INSERT FOR LOGGING THE TRANSACTION BEGIN TRANSACTION --CODE CANCELLED BY USER --UPDATE FOR LOGGING THE TRANSACTION'S SUCCESS COMMIT TRANSACTION END TRY BEGIN CATCH DECLARE @V_ERROR_NUM INT = ERROR_NUMBER(), @V_ERROR_MSG VARCHAR(1000)=ERROR_MESSAGE(), @V_ERROR_SEVERITY VARCHAR(100)=ERROR_SEVERITY(), @V_ERROR_STATE VARCHAR(10)=ERROR_STATE() --UPDATE FOR LOGGING THE TRANSACTION'S ERROR RAISERROR(@V_ERROR_MSG,@V_ERROR_SEVERITY,@V_ERROR_STATE); END CATCH SET ANSI_WARNINGS ON
原因分析
用户手动取消操作(如SSMS中点击「取消执行」)属于批处理终止事件,SQL Server会直接中断当前批处理的所有执行流程,TRY/CATCH块无法捕获这类事件——因为批处理被强制终止后,CATCH块的代码根本没有机会执行。
解决方案
1. 使用扩展事件捕获取消操作
这是SQL层最可靠的记录方式,通过创建扩展会话捕获sqlserver.cancel_session事件,将取消操作的信息持久化到目标存储:
-- 创建扩展会话 CREATE EVENT SESSION [CaptureUserCancels] ON SERVER ADD EVENT sqlserver.cancel_session( ACTION(sqlserver.session_id,sqlserver.sql_text,sqlserver.username) ) ADD TARGET package0.event_file(SET filename=N'C:\SQLLogs\UserCancels.xel') WITH (STARTUP_STATE=OFF) GO -- 启动会话 ALTER EVENT SESSION [CaptureUserCancels] ON SERVER STATE = START; GO
后续可以读取事件文件中的数据,或者配置目标为自定义表来直接记录到日志表中。
2. 应用层补充控制
如果是通过应用程序调用SQL脚本,可以在应用层捕获用户取消的信号(比如.NET中的SqlCommand.Cancel()事件),然后主动调用日志插入语句,确保取消操作被记录。
3. 代码层面的优化(仅针对常规错误)
当前代码中的SET XACT_ABORT ON仅能处理常规执行错误,无法影响用户取消这类强制终止事件。若要确保常规错误被捕获,现有TRY/CATCH逻辑是有效的,但对用户取消场景不适用。
内容的提问来源于stack exchange,提问作者RindoquesUwU
相关产品推荐
相关产品推荐

