SqlServer嵌套事务机制测试(一)

2014-11-24 14:48:07 · 作者: · 浏览: 0

SqlServer嵌套事务机制测试
今天我们主研究一下SqlServer中嵌套事务使用。代码能说明大多数问题,看代码。
1.嵌套事务提交原理测试 www.2cto.com
[c-sharp]
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))
结果:
Trancount before transaction: 0
After first BEGIN TRAN: 1
After second BEGIN TRAN: 2
After first COMMIT TRAN: 1
After second COMMIT TRAN: 0
我们可以得出: www.2cto.com
1.可以看到每一个BEGIN TRAN语句都会使@@TRANCOUNT增加1;
2.每一个COMMIT TRAN语句都会使@@TRANCOUNT减少1;
3.如前所述,一个值为0的@@TRANCOUNT意味着没有打开的事务;
4.因此,在@@TRANCOUNT值从1降到0时结束的事务发生在最外层事务提交的时候。
2. 嵌套事务回滚
2.1 嵌套事务回滚最外面事务,对内部事务有什么影响?
我们再来看一段代码:
[c-sharp]
-- 创建临时表
CREATE TABLE #TestTrans(Cola INT PRIMARY KEY,
Colb varchar(20) NOT NULL);
/* 外部事务 */
BEGIN TRANSACTION OutOfProc;
--内部事务
BEGIN TRANSACTION InProc
INSERT INTO #TestTrans VALUES (1,'aaaa');
COMMIT TRANSACTION InProc;
/* 回滚外部事务,也会回滚内部事务 */
ROLLBACK TRANSACTION OutOfProc;
/*无数据,1说明最外层事务回滚,里面所有的事务都会回滚 */
SELECT * FROM #TestTrans;
drop table #TestTrans
结果:没有数据。
现在看来:无论数据是否提交,只要最外层回滚了就会导致所有内部所有嵌套类回滚。
2.2 嵌套事务回滚内部嵌套事务呢?
再看一段代码:
[c-sharp]
-- 创建临时表
CREATE TABLE #TestTrans(Cola INT PRIMARY KEY,
Colb varchar(20) NOT NULL);
/* 外部事务 */
BEGIN TRANSACTION OutOfProc;
--内部事务
BEGIN TRANSACTION InProc
INSERT INTO #TestTrans VALUES (1,'aaaa');
ROLLBACK TRANSACTION InProc;
--内部事务2
BEGIN TRANSACTION InProc2
INSERT INTO #TestTrans VALUES (2,'222');
COMMIT TRANSACTION InProc2;
/* 提交外部事务 */
COMMIT TRANSACTION OutOfProc;
/*出错:内部事务未回滚,内部事务不能回滚,"找不到该名称的事务或保存点。" */
SELECT * FROM #TestTrans;
drop table #TestTrans
结果:
有异常信息:
(1 行受影响)
消息 6401,级别 16,状态 1,第 9 行
无法回滚 InProc。找不到该名称的事务或保存点。
(1 行受影响)
(2 行受影响)
我们可以看到:ROLLBACK TRANSACTION InProc 是错误的。原因是没有保存还原点 InProc。
代码应该改为如下(具体原因请往下看):
[sql]
BEGIN TRANSACTION InProc
save tran InProc;
INSERT INTO #TestTrans VALUES (1,'aaaa');
ROLLBACK TRANSACTION InProc;
操作前保存好回滚点(save tran InProc),回滚时指定当时保存的位置,SqlServer才知道回滚到哪儿去。
3. 事务原理
往下读之前必须了解:全局变量@@trancount 可以确定是否存在打开的事务及其嵌套的深度。
提交的事务不能撤销或回滚。
当不存在打开的事务时,@@trancount 等于 0。
执行 begin tran [tranName]语句将 @@trancount 增加 1。
执行commit tran [tranName]语句将 @@trancount 减小 1。
执行 rollback tran 会回滚整个事务并设置@@trancount 为 0。
执行 " rollback tran tranName"语句时有两种情况:
if(tranName 之前 是用 " Save Tran tranName" ) @@trancount值不变
否则,@trancount 减小1
具体测试代码:
[sql]
-- 创建临时表
CREATE TABLE #TestTrans(Cola INT PRIMARY KEY,
Colb varchar(20) NOT NULL);
select @@TRANCOUNT '未开外部事务';
/* 外部事务 */
BEGIN TRANSACTION OutOfProc;
select @@TRANCOUNT '开外部事务';
--内部事务
BEGIN TRANSACTION InProc