如何解决SQL Server存储过程报告执行成功,但其中的查询未执行
我们使用一组存储过程来实现我们的ETL管道之一,该管道依赖于使用推送策略的链接服务器。存储过程在SQL Server代理作业中一步一步运行。这些服务器位于相同的VLAN中,并具有10GBPS的连接。
我们意识到拉动策略是理想的,并且正在努力将这种方法应用于我们的工作负载。
ETL代理通常是成功的,并且在相当长的一段时间内一直是可行的解决方案。一个或多个存储过程将间歇性地报告成功执行,但实际上不执行。我已经多次验证了这种情况。
代理历史记录表明未发生任何错误,并且我们的自定义错误表(由我们的错误处理程序存储过程填充)未显示迁移错误。所有存储过程都经过验证可以正常工作,并且没有逻辑错误,事实证明,在大多数情况下,数据是成功
INSERT|UPDATE|DELETE
编辑的。
手动执行失败的存储过程不会产生不同的结果。关于这种情况的令人困惑的部分是,如果存储过程中包含的查询被手动提取并执行,它将成功INSERT|UPDATE|DELETE
(ing)数据。
我最好的猜测是,这可能是由缓存的查询计划引起的。不过,我完全不确定。
我们针对该用例的存储过程始终包含一个try / catch来处理和记录任何错误。在结构上,它们通常类似于以下内容:
CREATE PROCEDURE dbo.some_etl_proc
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRY
---------
-- delete
---------
DELETE at
FROM LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
LEFT JOIN SOME_DB.dbo.some_table AS st
ON st.some_table_id = at.some_table_id
WHERE st.some_table_id IS NULL;
---------
-- update
---------
UPDATE at
SET col_1 = st.col_1,col_2 = st.col_2
FROM LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
JOIN SOME_DB.dbo.some_table AS st
ON st.some_table_id = at.some_table_id;
---------
-- insert
---------
INSERT INTO LINKED_SERVER.ANOTHER_DB.dbo.another_table (col_1,col_2)
SELECT st.col_1,st.col_2
FROM SOME_DB.dbo.some_table AS st
LEFT JOIN LINKED_SERVER.ANOTHER_DB.dbo.another_table AS at
ON at.some_table_id = st.some_table_id
WHERE at.some_table_id IS NULL;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRAN;
-- we log the error here using a custom sproc
EXEC dbo.error_handler
RETURN 55555;
END CATCH;
END;
我们的错误处理程序如下:
CREATE PROCEDURE dbo.error_handler
AS
DECLARE @errmsg NVARCHAR(2048),@severity TINYINT,@state TINYINT,@errno INT,@proc sysname,@lineno INT;
SELECT @errmsg = ERROR_MESSAGE(),@severity = ERROR_SEVERITY(),@state = ERROR_STATE(),@errno = ERROR_NUMBER(),@proc = ERROR_PROCEDURE(),@lineno = ERROR_LINE();
IF @errmsg NOT LIKE '***%'
BEGIN
SELECT @errmsg = N'*** ' + COALESCE(QUOTENAME(@proc),'<dynamic SQL>') + N',Line ' + LTRIM(STR(@lineno)) + N'. Errno ' + LTRIM(STR(@errno)) + N': ' + @errmsg;
END;
INSERT INTO dbo.db_error
SELECT GETDATE(),SYSTEM_USER,@errno,@severity,@state,@lineno,@errmsg,@proc;
RAISERROR('%s',@errmsg);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。