如果基于此脚本设置回滚事务,脚本是否会获取光标中的下一个项目?
Does a script fetch the next item in the cursor if the transaction was rolled back based on this script setup?
我对游标不是很熟悉,只是想知道一件比较简单的事情。看一下下面脚本的结构,注意游标实例化的位置和位置closed/deallocated。如果脚本在我编写 /* most of the code here */
的地方死锁并且事务被回滚,然后重新尝试,当脚本尝试 fetch next
时会发生什么?由于执行从未到达 close/deallocate 游标行,我觉得在第二次尝试时游标似乎会获取第二行。请注意,我并不是说这是正确编写的 - 我觉得我遇到的问题好像是由于在提交事务后游标被释放所致。
declare LPCursor cursor for
/*
...
*/
while (@deadlockretries <= @Maxlockretries)
begin
begin try
begin transaction
fetch next from LPCursor into @var1, @var2, @var3
while (@@fetch_status = 0)
begin
/* most of the code here */
end
commit transaction
close LPCursor
deallocate LPCursor
end try
begin catch
if (error_number() = 1205)
begin
if xact_state() <> 0
begin
rollback transaction
end
end
end catch
end
它将获取下一个,但我假设您知道这样做会导致 "processing" 块丢失,因为您在中间将其回滚。无论哪种方式,这里都会修改您的代码以向您展示它将如何前进:
CREATE TABLE #tmp(VAL1 varchar(10), VAL2 varchar(10), VAL3 varchar(10))
INSERT INTO #tmp VALUES('val1_1','val1_2','val1_3')
INSERT INTO #tmp VALUES('val2_1','val2_2','val2_3')
INSERT INTO #tmp VALUES('val3_1','val3_2','val3_3')
INSERT INTO #tmp VALUES('val4_1','val4_2','val4_3')
INSERT INTO #tmp VALUES('val5_1','val5_2','val5_3')
INSERT INTO #tmp VALUES('val6_1','val6_2','val6_3')
INSERT INTO #tmp VALUES('val7_1','val7_2','val7_3')
DECLARE @deadlockretries int = 0
declare @Maxlockretries int = 3
declare @var1 varchar(10)
declare @var2 varchar(10)
declare @var3 varchar(10)
DECLARE LPCursor cursor for SELECT VAL1, val2, val3 from #tmp
open LPCursor
while (@deadlockretries <= @Maxlockretries)
begin
PRINT 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
begin try
begin transaction
fetch next from LPCursor into @var1, @var2, @var3
-- print @var1 + @var2 + @var3
while (@@fetch_status = 0)
begin
print @var1 + @var2 + @var3
/* most of the code here */
select 1/0
fetch next from LPCursor into @var1, @var2, @var3
end
commit transaction
SET @deadlockretries = @Maxlockretries
close LPCursor
deallocate LPCursor
end try
begin catch
PRINT 'ERROR'
print error_number()
if (error_number() = 8134)
begin
if xact_state() <> 0
begin
PRINT 'ROLLBACK'
rollback transaction
end
end
end catch
PRINT 'END'
SET @deadlockretries += 1
end
IF CURSOR_STATUS('global','LPCursor')>=-1
BEGIN
DEALLOCATE LPCursor
END
我对游标不是很熟悉,只是想知道一件比较简单的事情。看一下下面脚本的结构,注意游标实例化的位置和位置closed/deallocated。如果脚本在我编写 /* most of the code here */
的地方死锁并且事务被回滚,然后重新尝试,当脚本尝试 fetch next
时会发生什么?由于执行从未到达 close/deallocate 游标行,我觉得在第二次尝试时游标似乎会获取第二行。请注意,我并不是说这是正确编写的 - 我觉得我遇到的问题好像是由于在提交事务后游标被释放所致。
declare LPCursor cursor for
/*
...
*/
while (@deadlockretries <= @Maxlockretries)
begin
begin try
begin transaction
fetch next from LPCursor into @var1, @var2, @var3
while (@@fetch_status = 0)
begin
/* most of the code here */
end
commit transaction
close LPCursor
deallocate LPCursor
end try
begin catch
if (error_number() = 1205)
begin
if xact_state() <> 0
begin
rollback transaction
end
end
end catch
end
它将获取下一个,但我假设您知道这样做会导致 "processing" 块丢失,因为您在中间将其回滚。无论哪种方式,这里都会修改您的代码以向您展示它将如何前进:
CREATE TABLE #tmp(VAL1 varchar(10), VAL2 varchar(10), VAL3 varchar(10))
INSERT INTO #tmp VALUES('val1_1','val1_2','val1_3')
INSERT INTO #tmp VALUES('val2_1','val2_2','val2_3')
INSERT INTO #tmp VALUES('val3_1','val3_2','val3_3')
INSERT INTO #tmp VALUES('val4_1','val4_2','val4_3')
INSERT INTO #tmp VALUES('val5_1','val5_2','val5_3')
INSERT INTO #tmp VALUES('val6_1','val6_2','val6_3')
INSERT INTO #tmp VALUES('val7_1','val7_2','val7_3')
DECLARE @deadlockretries int = 0
declare @Maxlockretries int = 3
declare @var1 varchar(10)
declare @var2 varchar(10)
declare @var3 varchar(10)
DECLARE LPCursor cursor for SELECT VAL1, val2, val3 from #tmp
open LPCursor
while (@deadlockretries <= @Maxlockretries)
begin
PRINT 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
begin try
begin transaction
fetch next from LPCursor into @var1, @var2, @var3
-- print @var1 + @var2 + @var3
while (@@fetch_status = 0)
begin
print @var1 + @var2 + @var3
/* most of the code here */
select 1/0
fetch next from LPCursor into @var1, @var2, @var3
end
commit transaction
SET @deadlockretries = @Maxlockretries
close LPCursor
deallocate LPCursor
end try
begin catch
PRINT 'ERROR'
print error_number()
if (error_number() = 8134)
begin
if xact_state() <> 0
begin
PRINT 'ROLLBACK'
rollback transaction
end
end
end catch
PRINT 'END'
SET @deadlockretries += 1
end
IF CURSOR_STATUS('global','LPCursor')>=-1
BEGIN
DEALLOCATE LPCursor
END