伤情的热水瓶 · 关于RSA加解密的异常 ...· 1 月前 · |
旅行中的闹钟 · zting科技_高分内容_个人页_第15页_ ...· 1 年前 · |
茫然的显示器 · ExcelHelper 通用类 - ...· 1 年前 · |
闯红灯的马克杯 · $ - 字符串内插 - 格式字符串输出 | ...· 1 年前 · |
耍酷的黑框眼镜 · vue 在浏览器的控制台打印变量 - 掘金· 1 年前 · |
作为 在此演示 ,
如果我有一个内部存储过程,这总是没有错误回滚。
CREATE PROCEDURE [inner] AS BEGIN
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
IF (1 + 1 = 2) BEGIN
ROLLBACK TRANSACTION;
END ELSE BEGIN
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 BEGIN
ROLLBACK TRANSACTION;
END CATCH
END
和一个外部SP调用内部,
CREATE PROCEDURE [outer] AS BEGIN
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
EXEC [inner];
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 BEGIN
ROLLBACK TRANSACTION;
;THROW;
END CATCH
END
然后,我叫外SP,
EXEC [outer];
我知道这个错误
Msg 266 Level 16 State 2 Line 0
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements.
Previous count = 1, current count = 0.
现在,最初这不是我所期望的。
我认为正在发生的事情,
公理:
BEGIN TRANSACTION
总是使
@@TRANCOUNT
增加1;
COMMIT TRANSACTION
总是使
@@TRANCOUNT
减少1;
ROLLBACK TRANSACTION
总是将
@@TRANCOUNT
重置为0;
@@TRANCOUNT
更改为除0以外的任何值时,其他任何操作都不会发生。
所以,一步一步,
BEGIN TRANSACTION
将
@@TRANCOUNT
设置为
1
。
@@TRANCOUNT
1
调用内部。
ROLLBACK TRANSACTION
将
@@TRANCOUNT
重置为
0
。
@@TRANCOUNT
0
一起返回外部。
@@TRANCOUNT
中的不匹配,因此会引发上述错误。
所以我的问题是
我的理解正确吗?规范文档在哪里?
编写存储过程的最佳方法是什么,它可能希望回滚自己的更改,以便可以直接在自己的批处理中或从另一个事务中调用它?
发布于 2022-08-18 09:57:48
是的,你的理解是正确的。
在存储过程中,没有
ROLLBACK TRANSACTION
或transaction_name
的savepoint_name
语句将所有语句回滚到最外层的BEGIN TRANSACTION
。存储过程中的ROLLBACK TRANSACTION
语句在存储过程完成时使@@TRANCOUNT
具有与调用存储过程时的@@TRANCOUNT
值不同的值,从而产生一条信息性消息。此消息不影响后续处理。
我不知道为什么它说“不影响后续处理”,因为这是
显然是假的
:相反,它抛出一个严重性为16的错误,这个错误可以用
BEGIN CATCH
捕获。
如果您确实希望使用这样的嵌套事务,并且只能够部分回滚它们,那么它就会变得更加复杂。
如果没有交易,您必须有条件地开始一项事务。然后,您必须
SAVE
一个保存点。然后,每个回滚都必须有条件地回滚整个事务,或者只回滚保存点。
CREATE PROCEDURE [inner] AS BEGIN
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY
DECLARE @tranCount int = @@TRANCOUNT;
IF @tranCount = 0
BEGIN TRANSACTION;
SAVE TRANSACTION innerSave;
IF (1 + 1 = 2) BEGIN
IF @tranCount = 0
ROLLBACK;
ROLLBACK TRANSACTION innerSave;
END ELSE BEGIN
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 BEGIN
IF @tranCount = 0
耍酷的黑框眼镜 · vue 在浏览器的控制台打印变量 - 掘金 1 年前 |