Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Транзакции: закрыть внутри процедуры / 15 сообщений из 15, страница 1 из 1
27.11.2019, 12:16
    #39894977
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Почему получаю ошибку в таком случае:
процедура открывает транзакцию, вызывает вторую, которая закрывает внутри.
Хотелось сделать так: большая процедура отрабатывает и в конце вызывается такой "чистильщик", которая кроме всего закрывает, если остались открытые

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ptest]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[ptest] AS'
END
GRANT EXECUTE on [dbo].[ptest] to public;
GO
ALTER  PROCEDURE [dbo].[ptest]
@parrollback bit = 0
AS
BEGIN
SET NOCOUNT ON
select @@TRANCOUNT as '@@TRANCOUNT:[ptest] '
if @parrollback is not null and @parrollback>0
	if @@TRANCOUNT>0 rollback tran;
END
GO

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[pcaller]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'CREATE PROCEDURE [dbo].[pcaller] AS'
END
GRANT EXECUTE on [dbo].[pcaller] to public;
GO
ALTER  PROCEDURE [dbo].[pcaller]
AS
BEGIN
SET NOCOUNT ON
begin tran
select @@TRANCOUNT as '@@TRANCOUNT: before [ptest]'
exec ptest 1
select @@TRANCOUNT as '@@TRANCOUNT: after [ptest] '
if @@TRANCOUNT>0 rollback tran;
END
GO
-------------

exec pcaller 


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ptest]') AND type in (N'P', N'PC'))
	drop proc pcaller
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ptest]') AND type in (N'P', N'PC'))
	drop proc ptest
...
Рейтинг: 0 / 0
27.11.2019, 12:53
    #39895005
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Ролг Хупин,

непонятно - вторая процедура закрывает транзакцию, без её открытия? Почему это происходит?
...
Рейтинг: 0 / 0
27.11.2019, 13:26
    #39895031
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Владислав Колосов
Ролг Хупин,

непонятно - вторая процедура закрывает транзакцию, без её открытия? Почему это происходит?


она по идее для того и предназначена
в вызывающей процедуре открывается транзакция, что-то делается, может обломаться и вторая проверяет и закрывает, если остались открытые.
Реально вторая процедура вызывается в
begin try
...
-- тут вызвается несколько процедур, одна из которых может выскочить с ошибкой
end try
begin catch
exec ptest,1
end catch
...
Рейтинг: 0 / 0
27.11.2019, 13:27
    #39895032
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
и ошибка
Msg 266, Level 16, State 2, Procedure ptest, Line 0 [Batch Start Line 34]
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.

Вопрос: почему нельзя так сделать? во второй процедуре закрыть транзакции, точнее откатить?
...
Рейтинг: 0 / 0
27.11.2019, 14:24
    #39895087
Minamoto
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Ролг Хупин,

потому что вы взорвете мозг тому, кто будет дорабатывать этот код после вас.
Серьезно - не надо так делать.
Сделайте себе лучше шаблон, который будет корректно поднимать транзакцию, если необходимо, или сохранять, если он запускается в уже существующей транзакции и так же откатывать либо всю транзакцию, либо откатываться к сохраненной точке.

Как пример: http://rusanu.com/2009/06/11/exception-handling-and-nested-transactions/

Вот ответ от человека, который называет себя "Technical Architect working at the Microsoft Technology Center":

https://dba.stackexchange.com/questions/212115/handling-transaction-count-after-execute-indicates-a-mismatching-number-of-begi Performing a ROLLBACK in a stored procedure that didn't start the transaction is also an error, and will generate this message.
...
Рейтинг: 0 / 0
27.11.2019, 14:33
    #39895090
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Minamoto
Ролг Хупин,

потому что вы взорвете мозг тому, кто будет дорабатывать этот код после вас.
Серьезно - не надо так делать.
Сделайте себе лучше шаблон, который будет корректно поднимать транзакцию, если необходимо, или сохранять, если он запускается в уже существующей транзакции и так же откатывать либо всю транзакцию, либо откатываться к сохраненной точке.

Как пример: http://rusanu.com/2009/06/11/exception-handling-and-nested-transactions/

Вот ответ от человека, который называет себя "Technical Architect working at the Microsoft Technology Center":

https://dba.stackexchange.com/questions/212115/handling-transaction-count-after-execute-indicates-a-mismatching-number-of-begi Performing a ROLLBACK in a stored procedure that didn't start the transaction is also an error, and will generate this message.


про взрыв мозга - согласен, но, скажем, вызывающая процедура вызвает 5 разных, одна из которых генерирует ошибку.
Я вижу в таком случае - на выходе вызывающей остается незакрытая транзакция.
Вот и подумал сделать процедуру типа ptest,
но хотелось бы понять - почему ошибка возникает?
...
Рейтинг: 0 / 0
27.11.2019, 14:41
    #39895097
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Ролг Хупин

Я вижу в таком случае - на выходе вызывающей остается незакрытая транзакция.

а не надо такое видеть.
во всех внутренних в catch -- throw
во внешней в catch -- rollback
...
Рейтинг: 0 / 0
27.11.2019, 14:46
    #39895100
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Yasha123
Ролг Хупин

Я вижу в таком случае - на выходе вызывающей остается незакрытая транзакция.

а не надо такое видеть.
во всех внутренних в catch -- throw
во внешней в catch -- rollback


так работает, но тяга к знаниям закрутила, хотелось понять.
внутренние процедуры писаны не мной, туда Заратустра не позволяет вмешиваться.
...
Рейтинг: 0 / 0
27.11.2019, 15:50
    #39895128
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Ролг Хупин,

это поведение by design

описанно в справке по rollback.

можете поиграться:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create or alter proc usp_test1
as 
begin transaction
go
create or alter proc usp_test2
as
if xact_state() <> 0 rollback transaction
go

select @@TRANCOUNT
exec usp_test1
select @@TRANCOUNT
exec usp_test2
select @@TRANCOUNT



add: хотя на самом деле не совсем точно, потому что в справке написано что "This message does not affect subsequent processing"
а по факту транзакция переходит в uncommitable state
...
Рейтинг: 0 / 0
27.11.2019, 17:31
    #39895179
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Ролг Хупин
но хотелось бы понять - почему ошибка возникает?
Потому что МС установил такое правило.
...
Рейтинг: 0 / 0
27.11.2019, 18:01
    #39895196
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Yasha123
Ролг Хупин

Я вижу в таком случае - на выходе вызывающей остается незакрытая транзакция.

а не надо такое видеть.
во всех внутренних в catch -- throw
во внешней в catch -- rollback


Садись - неуд.

Код: sql
1.
set xact_abort on;
...
Рейтинг: 0 / 0
27.11.2019, 18:42
    #39895221
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
set xact_abort on;

begin tran 
   create table dbo.test(id int);
   drop table dbo.nonexistingtable;
commit;

select *
from dbo.test;


что-то нету роллбэка, а xact_abort on есть
...
Рейтинг: 0 / 0
28.11.2019, 06:37
    #39895333
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
Yasha123
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
set xact_abort on;

begin tran 
   create table dbo.test(id int);
   drop table dbo.nonexistingtable;
commit;

select *
from dbo.test;


что-то нету роллбэка, а xact_abort on есть


Суслика нет, а он есть.

Фсе работает. Там где надо.
...
Рейтинг: 0 / 0
28.11.2019, 10:51
    #39895425
Yasha123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
aleks222

Суслика нет, а он есть.

и имя ему алекс-двоечник.
роллбэка правда так и нет в моем примере

aleks222

Фсе работает. Там где надо.

еще бы.
надо в паре с try..catch.
который суслик не захотел признать
...
Рейтинг: 0 / 0
28.11.2019, 11:17
    #39895445
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Транзакции: закрыть внутри процедуры
aleks222
Yasha123
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
set xact_abort on;

begin tran 
   create table dbo.test(id int);
   drop table dbo.nonexistingtable;
commit;

select *
from dbo.test;


что-то нету роллбэка, а xact_abort on есть


Суслика нет, а он есть.

Фсе работает. Там где надо.


в моем примере (см. первый мєсиджь) не работает
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Транзакции: закрыть внутри процедуры / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]