SQL Server 2005之嵌套事务学习

SQL Server 2005之嵌套事务学习


显 式事务可以嵌套,即在显式事务中开始另一个显式事务是可能的。支持嵌套事务的最重要原因是为了允许在存储过程中使用事务而不必顾及这个事务本身是否是在另 一个事务中被调用的。但是SQL Server是如何处理嵌套事务的?我们可以通过两个简单的示例来探究一下嵌套事务。
?       探究嵌套事务
1.    启动SQL Server Management Studio并打开一个“新建查询”窗口。
2.    通过@@TRANCOUNT来发现SQL Server是如何处理嵌套事务的。键入并执行以下批(此例的代码包含在示例文件NestingTransactions.sql中):
PRINT 'Trancount before transaction: ' + CAST(@@trancount as char(1))
BEGIN TRAN
    PRINT 'After first BEGIN TRAN: ' + CAST(@@trancount as char(1))
    BEGIN TRAN
        PRINT 'After second BEGIN TRAN: ' + CAST(@@trancount as char(1))
    COMMIT TRAN
    PRINT 'After first COMMIT TRAN: ' + CAST(@@trancount as char(1))
COMMIT TRAN
PRINT 'After second COMMIT TRAN: ' + CAST(@@trancount as char(1))
3.    在结果中,可以看到每一个BEGIN TRAN 语句都会使@@TRANCOUNT增加1并且每一个COMMIT TRAN语句都会使其减少1。如前所述,一个值为0的@@TRANCOUNT意味着没有打开的事务。因此,在@@TRANCOUNT值从1降到0时结束的 事务发生在外层事务提交的时候。因此,每一个内部事务都需要提交。由于事务起始于第一个BEGIN TRAN并结束于最后一个COMMIT TRAN,因此最外层的事务决定了是否完全提交内部的事务。如果最外层的事务没有被提交,其中嵌套的事务也不会被提交。
4.    键入并执行以下批来检验事务回滚时所发生的情况:
USE AdventureWorks
BEGIN TRAN
    PRINT 'After 1st BEGIN TRAN: ' + CAST(@@trancount as char(1))
    BEGIN TRAN
        PRINT 'After 2nd BEGIN TRAN: ' + CAST(@@trancount as char(1))
            BEGIN TRAN
            PRINT 'After 3rd BEGIN TRAN: ' + CAST(@@trancount as char(1))
            UPDATE Person.Contact
            SET EmailAddress = 'test@test.at'
            WHERE ContactID = 20
            COMMIT TRAN
        PRINT 'After first COMMIT TRAN: ' + CAST(@@trancount as char(1))
ROLLBACK TRAN
PRINT 'After ROLLBACK TRAN: ' + CAST(@@trancount as char(1))
SELECT EmailAddress FROM Person.Contact
WHERE ContactID = 20;
5.    在这个示例中,联系人的电子邮件地址在一个嵌套事务中被更新,这会被立即提交。然后ROLLBACK TRAN被执行。ROLLBACK TRAN将@@TRANCOUNT减为0并回滚整个事务及其中嵌套的事务,无论它们是否已经被提交。因此,嵌套事务中所做的更新被回滚,数据没有任何改变。
始终牢记,在嵌套的事务中,只有最外层的事务决定着是 否提交内部事务。每一个COMMIT TRAN语句总是应用于最后一个执行的BEGIN TRAN。因此,对于每一个BEGIN TRAN,必须调用一个COMMIT TRAN来提交事务。ROLLBACK TRAN语句总是属于最外层的事务,并且因此总是回滚整 个事务而不论其中打开了多少嵌套事务。正因为此,管理嵌套事务很复杂。正如本节最初提到的那样,如果每一个嵌套存储过程都在自身中开始一个事务,那么嵌套 事务大部分会发生在嵌套存储过程中。要避免嵌套事务,可以在过程开始处检查@@TRANCOUNT的值,以此来确定是否需要开始一个事务。如果 @@TRANCOUNT大于0,因为过程已经处于一个事务中并且调用实例可以在错误发生时回滚事务。
此条目发表在未分类分类目录,贴了标签。将固定链接加入收藏夹。