回滚后持久化日志到N-deep
Persisting log in N-deep after rollback
我的一个存储过程遇到问题。
我 运行 一个 main
过程,在事务中调用一个 recursiveChildren
调用自己的过程。
像这样:
EXEC main
{
EXEC log 'START'
BEGIN TRANSACTION
BEGIN TRY
EXEC recursiveChildren
{
IF ...
EXEC recursiveChildren
{
IF ...
EXEC recursiveChildren
{
...
}
END IF
EXEC log 'step X'
}
END IF
EXEC log 'step X'
}
IF ...
COMMIT;
ELSE
THROW error;
END TRY
BEGIN CATCH
ROLLBACK;
EXEC log 'ROLLBACK'
END CATCH
END TRANSACTION
EXEC log 'STOP'
}
如您所见,我调用了一个记录程序来跟踪我正在做的事情,但是如果我需要使用我的 THROW error
,我将丢失有关发生的事情的所有信息。
我读过 TSQL logging inside transaction 谈论日志和回滚,但是 table variable
不适合递归,因为它 READONLY
当用作过程的参数时。
回滚或不回滚时如何保留日志?
正如 Martin 所说,我的解决方案是在更新前将日志移至 var table。
如果有人遇到同样的问题,这里是代码:
CREATE PROCEDURE dbo.[main]
AS
BEGIN
WHILE EXISTS(SELECT 1 FROM #tmp)
BEGIN
SET @last_id_log = (SELECT MAX([id]) FROM Logs);
BEGIN TRANSACTION;
BEGIN TRY
SET @last_nb_error = @nb_error;
EXEC dbo.[child] @nb_error output; -- recursive call of child
IF( @nb_error - @last_nb_error = 0)
COMMIT TRANSACTION;
ELSE
THROW 66666, 'Error while child, ROLLBACK', 1;
END TRY
BEGIN CATCH
DECLARE @LogTable TABLE
([id] [int]
,[date] [datetime]
,[userName] [varchar](100)
,[error] [varchar](1000)
);
INSERT INTO @LogTable
SELECT *
FROM Logs
WHERE [Id] > @last_id_log
;
ROLLBACK TRANSACTION;
INSERT INTO Logs
SELECT *
FROM @LogTable
;
DELETE FROM @LogTable;
END CATCH
END
END
我的一个存储过程遇到问题。
我 运行 一个 main
过程,在事务中调用一个 recursiveChildren
调用自己的过程。
像这样:
EXEC main
{
EXEC log 'START'
BEGIN TRANSACTION
BEGIN TRY
EXEC recursiveChildren
{
IF ...
EXEC recursiveChildren
{
IF ...
EXEC recursiveChildren
{
...
}
END IF
EXEC log 'step X'
}
END IF
EXEC log 'step X'
}
IF ...
COMMIT;
ELSE
THROW error;
END TRY
BEGIN CATCH
ROLLBACK;
EXEC log 'ROLLBACK'
END CATCH
END TRANSACTION
EXEC log 'STOP'
}
如您所见,我调用了一个记录程序来跟踪我正在做的事情,但是如果我需要使用我的 THROW error
,我将丢失有关发生的事情的所有信息。
我读过 TSQL logging inside transaction 谈论日志和回滚,但是 table variable
不适合递归,因为它 READONLY
当用作过程的参数时。
回滚或不回滚时如何保留日志?
正如 Martin 所说,我的解决方案是在更新前将日志移至 var table。
如果有人遇到同样的问题,这里是代码:
CREATE PROCEDURE dbo.[main]
AS
BEGIN
WHILE EXISTS(SELECT 1 FROM #tmp)
BEGIN
SET @last_id_log = (SELECT MAX([id]) FROM Logs);
BEGIN TRANSACTION;
BEGIN TRY
SET @last_nb_error = @nb_error;
EXEC dbo.[child] @nb_error output; -- recursive call of child
IF( @nb_error - @last_nb_error = 0)
COMMIT TRANSACTION;
ELSE
THROW 66666, 'Error while child, ROLLBACK', 1;
END TRY
BEGIN CATCH
DECLARE @LogTable TABLE
([id] [int]
,[date] [datetime]
,[userName] [varchar](100)
,[error] [varchar](1000)
);
INSERT INTO @LogTable
SELECT *
FROM Logs
WHERE [Id] > @last_id_log
;
ROLLBACK TRANSACTION;
INSERT INTO Logs
SELECT *
FROM @LogTable
;
DELETE FROM @LogTable;
END CATCH
END
END