Взаимосвязь между транзакциями в вложенных хранимых процедурах?

Я поместил транзакции во все мои «установленные» процедуры. Нет проблем. Все работает.

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

Так будет счастливая баня.

  • Я в ProcA и начинаю транзакцию.
  • Он вызывает ProcB и начинает транзакцию.
  • ProcB успешно и совершает.
  • ProcA успешно и совершает.

Однако, что произойдет, если ProcB не удастся, откатится и повторит ошибку. Это должно привести к откату ProcA, а также правильному?

Что делать, если ProcB преуспевает, комментирует, затем ProcA впоследствии терпит неудачу, а rollbackback … произойдет ли то, что произошло в ProcB? или он совершается?

Мне нужно, чтобы эти два человека работали вместе, либо оба успешно, либо потерпели неудачу, и оба были отброшены назад. Каков наилучший способ обеспечить это?

Я работаю с Microsoft SQL Server 2008 R2 (SP1)

Примечание. Если ProcB требует транзакции, потому что ее можно вызывать без обхода пакета ProcA. И технически, ProcA не всегда будет вызывать ProcB (зависит от ввода).

Вот простая демонстрация, показывающая, что происходит с вложенными трансациями:

CREATE TABLE TranTest (Field1 INTEGER) BEGIN TRANSACTION SELECT @@TRANCOUNT -- 1 open transaction INSERT TranTest VALUES (1) BEGIN TRANSACTION SELECT @@TRANCOUNT -- 2 open transactions INSERT TranTest VALUES (2) ROLLBACK TRANSACTION -- this rolls back ALL transaction SELECT @@TRANCOUNT -- 0 open transactions (you may have expected 1?) SELECT * FROM TranTest -- No rows 

Вместо этого ROLLBACK выше, если вы выполнили COMMIT TRANSACTION, это фактически ничего не делает, а затем уменьшает @@ TRANCOUNT. Таким образом, вам тогда понадобится либо COMMIT внешняя транзакция (которая будет COMMIT обе строки в таблице), либо сделать ROLLBACK, из-за чего строки не будут привязаны к таблице.

Вот ссылка MSDN на вложенные транзакции: http://msdn.microsoft.com/en-us/library/ms189336.aspx

Просто используйте XACT_ABORT ON, и вы все настроены. Запустите следующий скрипт и убедитесь сами:

 CREATE DATABASE ak_test; GO USE ak_test; GO CREATE TABLE dbo.a(i INT CONSTRAINT a_CannotInsertNegative CHECK(i>=0)); GO CREATE TABLE dbo.b(i INT CONSTRAINT b_CannotInsertNegative CHECK(i>=0)); GO CREATE PROCEDURE dbo.innerProc @i INT AS SET XACT_ABORT ON ; BEGIN TRAN INSERT b(i)VALUES(@i); COMMIT; GO CREATE PROCEDURE dbo.outerProc @i1 INT, @i2 INT, @i3 INT AS SET XACT_ABORT ON ; BEGIN TRAN INSERT a(i)VALUES(@i1); EXEC innerProc @[email protected]; INSERT a(i)VALUES(@i3); COMMIT; GO -- succeeds EXEC dbo.outerProc 1, 2, 3; SELECT * FROM dbo.a; SELECT * FROM dbo.b; GO -- inner proc fails EXEC dbo.outerProc 2, -3, 4; GO SELECT * FROM dbo.a; SELECT * FROM dbo.b; GO -- second insert in outer proc fails EXEC dbo.outerProc 3, 4, -5; GO SELECT * FROM dbo.a; SELECT * FROM dbo.b; 

Я параноик по поводу транзакций (эта транзакция осталась открытой на Production, когда никто не заметил в течение получаса …), поэтому я бы деформировал потенциально внутреннюю транзакцию следующим образом:

 CREATE PROCEDURE etcetc ... DECLARE @IsTransaction bit = 0 IF @@trancount > 0 BEGIN BEGIN TRANSACTION SET @IsTransaction = 1 END ... IF @IsTransaction = 1 BEGIN COMMIT -- or ROLLBACk, as necessary END 

Вся обработка транзакций (и обработка ошибок, возникающих в транзакции) должна обрабатываться на любом уровне запуска транзакции.

(И кто-нибудь еще заметил, что BOL фактически не говорит, что происходит, когда вы выдаете ROLLBACK для именованной транзакции, которая не является самой внешней транзакцией? Они описывают каждую другую перестановку …)

  • Ошибка преобразования типа данных nvarchar в int - при выполнении хранимой процедуры
  • Можем ли мы написать предложение IN в инструкции ELSE IF в SQL Server 2008
  • SQL Server Простой пример использования разделителя в хранимой процедуре
  • Как заставить DataSet распознавать имена таблиц из хранимой процедуры?
  • разница в производительности между пользовательской функцией и хранимыми процедурами
  • Выполнение хранимой процедуры из командного файла
  • Как шифровать все существующие хранимые процедуры базы данных
  • чтение выходной хранимой процедуры, которая возвращает несколько наборов записей в sql 2005
  • Можно ли использовать хранимую процедуру в качестве подзапроса в SQL Server 2008?
  • не может получить выходной параметр из SP, вызванного из другого SP
  • Типы данных varchar и varbinary (max) несовместимы в операторе добавления
  • Давайте будем гением компьютера.