Sybase嵌套存储过程回滚问题(Sysbase11.5)

时间:2022-04-29 19:58:26
创建测试存储过程P_leve1,P_leve2如下:
create procedure P_level1
as
begin
    begin tran 
print '调用前事务级:%1!',@@trancount
execute P_level2
         print '调用后事务级:%1!',@@trancount
    commit tran 
end

create procedure P_level2
as
begin
    begin tran 
print '调用中事务级:%1!',@@trancount
    rollback tran
end

输出结果如下:

调用前事务级:1
调用中事务级:2
Server Message:  Number  266, Severity  10
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRAN is missing. Previous count = 1, Current count = 0. 
调用后事务级:0

执行存储过程时sybase对打开的事务进行计数。运行存储过程前后事务数若不相等则产生266号错误。但据Sybase事务机制,嵌套事务中任一层回滚时,回滚至第一层。从而在P_level2中回滚后事务数为0,与调用前的1不符。

该问题如何解决?是否在sybase嵌套存储过程中子过程不予许回滚,只能设置一个output参数,判断出错时用该参数返回错误代码,用commit平衡事务数,return,然后在*事务中判断output参数值,若出错则回滚。也就是说,Sybase只能在*事务中回滚,若多级存储过程嵌套,须一级一级上传返回值?

太繁琐了吧,请高手指点

7 个解决方案

#1


帮你顶!

#2


记住一个规则:
1、在事务中的任何一个没有名字的rollback tran会将@@trancount置为0,也就是所有的变化全部回滚;
2、在事务中的commit tran会将@@trancount减1,知道commit到@@trancount=0时才提交;

#3


你可以这么写:
create procedure P_level1
as
begin
    begin tran 
print '调用前事务级:%1!',@@trancount
execute P_level2
         print '调用后事务级:%1!',@@trancount
    commit tran 
end

create procedure P_level2
as
begin
if @@trancount > 0
save tran  aa
else
begin tran aa
print '调用中事务级:%1!',@@trancount
    rollback tran aa
end

#4


tolison兄:
我记得sybase在非*事务中是不允许带名字回滚的吧?在P_level2中用
rollback tran aa
同样会出错的

#5


虽然事务可以嵌套,但是只能回退最外层的事务

#6


存储过程中的事务回退,可以回退到save tran 事物名称的地方,如果没有命名事务,将回退到调用存储过程地方的第一个begin tran.
tolison应该是对的

#7


这样写没有问题


drop procedure P_level1

create procedure P_level1
as
begin
    begin tran tran1
print '调用前事务级:%1!',@@trancount
execute P_level2
    if @@error >0 
      begin
        select '执行过程错误' 
        rollback tran tran1
      return      
      end
    print '调用后事务级:%1!',@@trancount
    commit tran tran1
   print '提交后事务级:%1!',@@trancount

end

create procedure P_level2
as
begin
    begin tran 
print '调用中事务级:%1!',@@trancount
    if @@error >0 
      begin
        select '执行过程错误' 
        rollback tran tran1
      return      
      end
    commit tran 

end

exec P_level1

#1


帮你顶!

#2


记住一个规则:
1、在事务中的任何一个没有名字的rollback tran会将@@trancount置为0,也就是所有的变化全部回滚;
2、在事务中的commit tran会将@@trancount减1,知道commit到@@trancount=0时才提交;

#3


你可以这么写:
create procedure P_level1
as
begin
    begin tran 
print '调用前事务级:%1!',@@trancount
execute P_level2
         print '调用后事务级:%1!',@@trancount
    commit tran 
end

create procedure P_level2
as
begin
if @@trancount > 0
save tran  aa
else
begin tran aa
print '调用中事务级:%1!',@@trancount
    rollback tran aa
end

#4


tolison兄:
我记得sybase在非*事务中是不允许带名字回滚的吧?在P_level2中用
rollback tran aa
同样会出错的

#5


虽然事务可以嵌套,但是只能回退最外层的事务

#6


存储过程中的事务回退,可以回退到save tran 事物名称的地方,如果没有命名事务,将回退到调用存储过程地方的第一个begin tran.
tolison应该是对的

#7


这样写没有问题


drop procedure P_level1

create procedure P_level1
as
begin
    begin tran tran1
print '调用前事务级:%1!',@@trancount
execute P_level2
    if @@error >0 
      begin
        select '执行过程错误' 
        rollback tran tran1
      return      
      end
    print '调用后事务级:%1!',@@trancount
    commit tran tran1
   print '提交后事务级:%1!',@@trancount

end

create procedure P_level2
as
begin
    begin tran 
print '调用中事务级:%1!',@@trancount
    if @@error >0 
      begin
        select '执行过程错误' 
        rollback tran tran1
      return      
      end
    commit tran 

end

exec P_level1