Sql-Server-2008

保存事務:名稱是否是儲存過程的本地名稱?

  • February 22, 2012

在生產伺服器上發生了一些腳射。我解決了這個問題,但我現在很困惑。

有一部分儲存過程在失敗時保留狀態。也就是說,如果過程引發錯誤,它無論如何都可以安全地送出。這是用save transaction.

現在,我最初的理解是,您為事務設置的保存點名稱對於使用它的儲存過程來說是本地的。而在嵌套場景中,如果內部儲存過程同名保存,其實是不同的名字,一切正常。

為了確保我的這種理解是正確的,我設置了一個測試案例:

create table dbo.[footest] (
 v varchar(50) NULL
);
go

insert into dbo.footest(v) values ('Nothing'); go

create procedure dbo.[foo_test_tran_inner]
as
begin
 set nocount on;

 declare @foo int;

 begin tran;

 update dbo.footest set v = 'Inner, before savepoint';

 save tran the_constant_name;

 begin try
   update dbo.footest
   set v = 'Inner, after savepoint';

   set @foo = 1/0;
 end try
 begin catch
   rollback tran the_constant_name;
 end catch;


 commit tran;

 set @foo = 1/0;

 return 0;
end;
go

create procedure dbo.[foo_test_tran_outer]
as
begin
 set nocount on;

 begin tran;

 update dbo.footest set v = 'Outer, before savepoint';


 save tran the_constant_name;

 begin try
   update dbo.footest
   set v = 'Outer, after savepoint';

   exec dbo.foo_test_tran_inner;
 end try
 begin catch
   rollback tran the_constant_name;
 end catch;



 commit tran;

 return 0;
end;
go
begin tran;
exec dbo.foo_test_tran_outer;
commit tran;
select * from dbo.footest;

**這會產生“外部,在保存點之前”。**這意味著,保存點名稱是過程的本地名稱,並且在嵌套場景中被正確回滾。


在生產中,那些保持狀態的儲存過程正是這種模式。其中有更多程式碼,但如果你刪除它,只留下保存、回滾和送出,它將完全是上面顯示的內容。

但。它在生產中不起作用。相反,每個具有相同名稱的嵌套保存點似乎都覆蓋了先前的保存點,該保存點由呼叫過程創建。而當最外層的程式碼在收到異常後執行 a commit(相信內部回滾已正確完成)時,數據庫處於半螺旋狀態。如果應用於上面的範例,這將意味著選擇返回Inner, before savepoint

我使用調試器逐步完成了生產過程中的每一步,並確認執行正確地完成了所有預期save tran a_name的和rollback tran a_name.

為了解決生產中的問題,我替換了這個:

save tran the_constant_name;
...
rollback tran the_constant_name;

有了這個:

declare @savepoint varchar(32) = replace(newid(), '-', '');
save tran @savepoint;
...
rollback tran @savepoint;

並立即修復它。


那麼給了什麼?保存點名稱是否是儲存過程的本地名稱?

如果是,那麼為什么生產程式碼做了它所做的事情,並且如圖所示成功修復了?

如果不是,那麼為什麼上面的測試範例會這樣做呢?

不,它們不是儲存過程的本地。

如果您在具有簡單恢復模型的數據庫中執行以下命令

checkpoint
begin tran;
exec dbo.foo_test_tran_outer;
commit tran;
select * from dbo.footest;

select Operation,
      Context,
      [Savepoint Name],
      [Transaction Name] ,
      Description 
from sys.fn_dblog(NULL,NULL)

它給出了這些結果

+--------------------+----------+-------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|     Operation      | Context  |  Savepoint Name   | Transaction Name |                                                                                               Description                                                                                                |
+--------------------+----------+-------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| LOP_BEGIN_CKPT     | LCX_NULL | NULL              | NULL             |                                                                                                                                                                                                          |
| LOP_END_CKPT       | LCX_NULL | NULL              | NULL             | log_minRecoveryLsn 00000112:00001ce6:008e;log_replbeginlsn 00000000:00000000:0000;log_replnextlsn 00000000:00000000:0000;log_distbackuplsn 00000000:00000000:0000;log_distlastlsn 00000000:00000000:0000 |
| LOP_BEGIN_XACT     | LCX_NULL | NULL              | user_transaction | user_transaction;0x010500000000000515000000007dfcff481d5bed8a729370ee030000                                                                                                                              |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             |                                                                                                                                                                                                          |
| LOP_MARK_SAVEPOINT | LCX_NULL | the_constant_name | NULL             |                                                                                                                                                                                                          |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             |                                                                                                                                                                                                          |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             |                                                                                                                                                                                                          |
| LOP_MARK_SAVEPOINT | LCX_NULL | the_constant_name | NULL             |                                                                                                                                                                                                          |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             |                                                                                                                                                                                                          |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             | COMPENSATION                                                                                                                                                                                             |
| LOP_LOCK_XACT      | LCX_NULL | NULL              | NULL             | COMPENSATION                                                                                                                                                                                             |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             | COMPENSATION                                                                                                                                                                                             |
| LOP_MODIFY_ROW     | LCX_HEAP | NULL              | NULL             | COMPENSATION                                                                                                                                                                                             |
| LOP_LOCK_XACT      | LCX_NULL | NULL              | NULL             | COMPENSATION                                                                                                                                                                                             |
| LOP_COMMIT_XACT    | LCX_NULL | NULL              | NULL             |                                                                                                                                                                                                          |
+--------------------+----------+-------------------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

事務[Savepoint Name]日誌中記錄的不包含任何與儲存過程相關的唯一標識符。

如果刪除rollback tran the_constant_name;fromfoo_test_tran_inner那麼最終選擇的結果將更改為Inner, before savepoint顯示rollback tran the_constant_name;執行的 fromfoo_test_tran_outer只是回滾到該名稱的最新(未回滾)保存點並且不考慮儲存過程嵌套。

引用自:https://dba.stackexchange.com/questions/13629